Initial commit of project source code
Change-Id: I5bca47fffeeb8e3cde78a7849b331f6880a2ab44
Signed-off-by: erwanM <erwan.mahe.work@gmail.com>
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..694a248
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,29 @@
+[package]
+name = "hibou_efm"
+version = "0.1.0"
+authors = ["Erwan Mahe"]
+edition = "2018"
+
+license = "Eclipse-Public-License-2.0"
+description = "Holistic Interaction Behavioral Oracle Utility - hibou provides utilities for the analysis of traces and multi-traces of interaction models"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+image = "0.23.3" # for rendering interactions
+imageproc = "0.20.0" # ...
+strum = "0.18.0" # for as_static in the graphviz package and others
+strum_macros = "0.18.0" # ...
+rusttype = "0.8.3" # for fonts and scale for text in images
+pest = "2.1.3" # for pest parser
+pest_derive = "2.1.0" # ...
+clap = {version="2.33.1",features=["yaml"]} # for the command line interface
+# ===================
+tonic = "0.2"
+prost = "0.6"
+tokio = { version = "0.2", features = ["macros"] }
+bytes = "0.5.4"
+
+
+[build-dependencies]
+tonic-build = "0.2"
\ No newline at end of file
diff --git a/LICENSE_EPL-2.0.txt b/LICENSE_EPL-2.0.txt
new file mode 100644
index 0000000..cf85fdf
--- /dev/null
+++ b/LICENSE_EPL-2.0.txt
@@ -0,0 +1,267 @@
+Eclipse Public License - v 2.0
+
+ THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+ PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
+ OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+ a) in the case of the initial Contributor, the initial content
+ Distributed under this Agreement, and
+
+ b) in the case of each subsequent Contributor:
+ i) changes to the Program, and
+ ii) additions to the Program;
+ where such changes and/or additions to the Program originate from
+ and are Distributed by that particular Contributor. A Contribution
+ "originates" from a Contributor if it was added to the Program by
+ such Contributor itself or anyone acting on such Contributor's behalf.
+ Contributions do not include changes or additions to the Program that
+ are not Modified Works.
+
+"Contributor" means any person or entity that Distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which
+are necessarily infringed by the use or sale of its Contribution alone
+or when combined with the Program.
+
+"Program" means the Contributions Distributed in accordance with this
+Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement
+or any Secondary License (as applicable), including Contributors.
+
+"Derivative Works" shall mean any work, whether in Source Code or other
+form, that is based on (or derived from) the Program and for which the
+editorial revisions, annotations, elaborations, or other modifications
+represent, as a whole, an original work of authorship.
+
+"Modified Works" shall mean any work in Source Code or other form that
+results from an addition to, deletion from, or modification of the
+contents of the Program, including, for purposes of clarity any new file
+in Source Code form that contains any contents of the Program. Modified
+Works shall not include works that contain only declarations,
+interfaces, types, classes, structures, or files of the Program solely
+in each case in order to link to, bind by name, or subclass the Program
+or Modified Works thereof.
+
+"Distribute" means the acts of a) distributing or b) making available
+in any manner that enables the transfer of a copy.
+
+"Source Code" means the form of a Program preferred for making
+modifications, including but not limited to software source code,
+documentation source, and configuration files.
+
+"Secondary License" means either the GNU General Public License,
+Version 2.0, or any later versions of that license, including any
+exceptions or additional permissions as identified by the initial
+Contributor.
+
+2. GRANT OF RIGHTS
+
+ a) Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free copyright
+ license to reproduce, prepare Derivative Works of, publicly display,
+ publicly perform, Distribute and sublicense the Contribution of such
+ Contributor, if any, and such Derivative Works.
+
+ b) Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free patent
+ license under Licensed Patents to make, use, sell, offer to sell,
+ import and otherwise transfer the Contribution of such Contributor,
+ if any, in Source Code or other form. This patent license shall
+ apply to the combination of the Contribution and the Program if, at
+ the time the Contribution is added by the Contributor, such addition
+ of the Contribution causes such combination to be covered by the
+ Licensed Patents. The patent license shall not apply to any other
+ combinations which include the Contribution. No hardware per se is
+ licensed hereunder.
+
+ c) Recipient understands that although each Contributor grants the
+ licenses to its Contributions set forth herein, no assurances are
+ provided by any Contributor that the Program does not infringe the
+ patent or other intellectual property rights of any other entity.
+ Each Contributor disclaims any liability to Recipient for claims
+ brought by any other entity based on infringement of intellectual
+ property rights or otherwise. As a condition to exercising the
+ rights and licenses granted hereunder, each Recipient hereby
+ assumes sole responsibility to secure any other intellectual
+ property rights needed, if any. For example, if a third party
+ patent license is required to allow Recipient to Distribute the
+ Program, it is Recipient's responsibility to acquire that license
+ before distributing the Program.
+
+ d) Each Contributor represents that to its knowledge it has
+ sufficient copyright rights in its Contribution, if any, to grant
+ the copyright license set forth in this Agreement.
+
+ e) Notwithstanding the terms of any Secondary License, no
+ Contributor makes additional grants to any Recipient (other than
+ those set forth in this Agreement) as a result of such Recipient's
+ receipt of the Program under the terms of a Secondary License
+ (if permitted under the terms of Section 3).
+
+3. REQUIREMENTS
+
+3.1 If a Contributor Distributes the Program in any form, then:
+
+ a) the Program must also be made available as Source Code, in
+ accordance with section 3.2, and the Contributor must accompany
+ the Program with a statement that the Source Code for the Program
+ is available under this Agreement, and informs Recipients how to
+ obtain it in a reasonable manner on or through a medium customarily
+ used for software exchange; and
+
+ b) the Contributor may Distribute the Program under a license
+ different than this Agreement, provided that such license:
+ i) effectively disclaims on behalf of all other Contributors all
+ warranties and conditions, express and implied, including
+ warranties or conditions of title and non-infringement, and
+ implied warranties or conditions of merchantability and fitness
+ for a particular purpose;
+
+ ii) effectively excludes on behalf of all other Contributors all
+ liability for damages, including direct, indirect, special,
+ incidental and consequential damages, such as lost profits;
+
+ iii) does not attempt to limit or alter the recipients' rights
+ in the Source Code under section 3.2; and
+
+ iv) requires any subsequent distribution of the Program by any
+ party to be under a license that satisfies the requirements
+ of this section 3.
+
+3.2 When the Program is Distributed as Source Code:
+
+ a) it must be made available under this Agreement, or if the
+ Program (i) is combined with other material in a separate file or
+ files made available under a Secondary License, and (ii) the initial
+ Contributor attached to the Source Code the notice described in
+ Exhibit A of this Agreement, then the Program may be made available
+ under the terms of such Secondary Licenses, and
+
+ b) a copy of this Agreement must be included with each copy of
+ the Program.
+
+3.3 Contributors may not remove or alter any copyright, patent,
+trademark, attribution notices, disclaimers of warranty, or limitations
+of liability ("notices") contained within the Program from any copy of
+the Program which they Distribute, provided that Contributors may add
+their own appropriate notices.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities
+with respect to end users, business partners and the like. While this
+license is intended to facilitate the commercial use of the Program,
+the Contributor who includes the Program in a commercial product
+offering should do so in a manner which does not create potential
+liability for other Contributors. Therefore, if a Contributor includes
+the Program in a commercial product offering, such Contributor
+("Commercial Contributor") hereby agrees to defend and indemnify every
+other Contributor ("Indemnified Contributor") against any losses,
+damages and costs (collectively "Losses") arising from claims, lawsuits
+and other legal actions brought by a third party against the Indemnified
+Contributor to the extent caused by the acts or omissions of such
+Commercial Contributor in connection with its distribution of the Program
+in a commercial product offering. The obligations in this section do not
+apply to any claims or Losses relating to any actual or alleged
+intellectual property infringement. In order to qualify, an Indemnified
+Contributor must: a) promptly notify the Commercial Contributor in
+writing of such claim, and b) allow the Commercial Contributor to control,
+and cooperate with the Commercial Contributor in, the defense and any
+related settlement negotiations. The Indemnified Contributor may
+participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial
+product offering, Product X. That Contributor is then a Commercial
+Contributor. If that Commercial Contributor then makes performance
+claims, or offers warranties related to Product X, those performance
+claims and warranties are such Commercial Contributor's responsibility
+alone. Under this section, the Commercial Contributor would have to
+defend claims against the other Contributors related to those performance
+claims and warranties, and if a court requires any other Contributor to
+pay any damages as a result, the Commercial Contributor must pay
+those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
+BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
+TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+PURPOSE. Each Recipient is solely responsible for determining the
+appropriateness of using and distributing the Program and assumes all
+risks associated with its exercise of rights under this Agreement,
+including but not limited to the risks and costs of program errors,
+compliance with applicable laws, damage to or loss of data, programs
+or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
+PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
+SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under
+applicable law, it shall not affect the validity or enforceability of
+the remainder of the terms of this Agreement, and without further
+action by the parties hereto, such provision shall be reformed to the
+minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity
+(including a cross-claim or counterclaim in a lawsuit) alleging that the
+Program itself (excluding combinations of the Program with other software
+or hardware) infringes such Recipient's patent(s), then such Recipient's
+rights granted under Section 2(b) shall terminate as of the date such
+litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it
+fails to comply with any of the material terms or conditions of this
+Agreement and does not cure such failure in a reasonable period of
+time after becoming aware of such noncompliance. If all Recipient's
+rights under this Agreement terminate, Recipient agrees to cease use
+and distribution of the Program as soon as reasonably practicable.
+However, Recipient's obligations under this Agreement and any licenses
+granted by Recipient relating to the Program shall continue and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement,
+but in order to avoid inconsistency the Agreement is copyrighted and
+may only be modified in the following manner. The Agreement Steward
+reserves the right to publish new versions (including revisions) of
+this Agreement from time to time. No one other than the Agreement
+Steward has the right to modify this Agreement. The Eclipse Foundation
+is the initial Agreement Steward. The Eclipse Foundation may assign the
+responsibility to serve as the Agreement Steward to a suitable separate
+entity. Each new version of the Agreement will be given a distinguishing
+version number. The Program (including Contributions) may always be
+Distributed subject to the version of the Agreement under which it was
+received. In addition, after a new version of the Agreement is published,
+Contributor may elect to Distribute the Program (including its
+Contributions) under the new version.
+
+Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
+receives no rights or licenses to the intellectual property of any
+Contributor under this Agreement, whether expressly, by implication,
+estoppel or otherwise. All rights in the Program not expressly granted
+under this Agreement are reserved. Nothing in this Agreement is intended
+to be enforceable by any entity that is not a Contributor or Recipient.
+No third-party beneficiary rights are created under this Agreement.
+
+This Source Code may also be made available under the following
+Secondary License when the conditions for such availability set forth
+in the Eclipse Public License, v. 2.0 are satisfied:
+Apache License, Version 2.0.
+
+Copyright 2021 CentraleSupelec, CEA-LIST
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..dcd3932
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,20 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ tonic_build::compile_protos("src/SymbexServices.proto")?;
+ Ok(())
+}
\ No newline at end of file
diff --git a/examples/COMMANDS_linux.txt b/examples/COMMANDS_linux.txt
new file mode 100644
index 0000000..c928f3a
--- /dev/null
+++ b/examples/COMMANDS_linux.txt
@@ -0,0 +1,13 @@
+// Example commands to run
+
+./hibou_efm explore example_1.hsf
+
+./hibou_efm explore example_2.hsf
+
+./hibou_efm analyze example_3.hsf example_3_wpass.htf
+
+./hibou_efm analyze example_3.hsf example_3_fail_param.htf
+
+./hibou_efm analyze example_3.hsf example_3_fail_path.htf
+
+./hibou_efm analyze example_4.hsf example_4.htf
\ No newline at end of file
diff --git a/examples/COMMANDS_windows.txt b/examples/COMMANDS_windows.txt
new file mode 100644
index 0000000..efcac0b
--- /dev/null
+++ b/examples/COMMANDS_windows.txt
@@ -0,0 +1,13 @@
+// Example commands to run
+
+hibou_efm.exe explore example_1.hsf
+
+hibou_efm.exe explore example_2.hsf
+
+hibou_efm.exe analyze example_3.hsf example_3_wpass.htf
+
+hibou_efm.exe analyze example_3.hsf example_3_fail_param.htf
+
+hibou_efm.exe analyze example_3.hsf example_3_fail_path.htf
+
+hibou_efm.exe analyze example_4.hsf example_4.htf
\ No newline at end of file
diff --git a/examples/example_1.hsf b/examples/example_1.hsf
new file mode 100644
index 0000000..0a05afa
--- /dev/null
+++ b/examples/example_1.hsf
@@ -0,0 +1,37 @@
+@explore_option{
+ loggers = [graphic=svg];
+ pre_filters = [ max_depth = 3 ]
+}
+@message{
+ m1(Integer,Integer);
+ m2(Integer);
+ m3(Integer,Integer)
+}
+@variable{
+ x : Integer;
+ y : Integer;
+ z : Integer;
+ id : Integer
+}
+@lifeline{
+ l1;l2;l3
+}
+@init{
+ l2.id = 525;
+ l2.z = 23;
+ l3.id = 491;
+ l3.z = #
+}
+@seq(
+ m1(#,#) -> l1{x:=$0;y:=$1},
+ @alt(
+ @seq(
+ [(x>=y)]l1 -- m2((x*y)) -> l2{z:=(z-$0)},
+ l2 -- m3(z,id) -> l1
+ ),
+ @seq(
+ [(x<y)]l1 -- m2((y-x)) -> l3{z:=(z+$0)},
+ l3 -- m3(z,id) -> l1
+ )
+ )
+)
\ No newline at end of file
diff --git a/examples/example_2.hsf b/examples/example_2.hsf
new file mode 100644
index 0000000..52e65fb
--- /dev/null
+++ b/examples/example_2.hsf
@@ -0,0 +1,31 @@
+@explore_option{
+ loggers = [graphic=svg]
+}
+@message{
+ m;
+ out (Integer, Integer);
+ error
+}
+@variable{
+ x : Integer;
+ y : Integer
+}
+@lifeline{
+ a
+}
+@init{
+ a.x = #;
+ a.y = #
+}
+@seq(
+ @alt(
+ m -> a[((5<x)/\(x<y))],
+ [⊥]a -- error ->|
+ ),
+ @alt(
+ m ->a[(y<x)],
+ o
+ ),
+ m -> a[(y=7)],
+ m -> a
+)
\ No newline at end of file
diff --git a/examples/example_3.hsf b/examples/example_3.hsf
new file mode 100644
index 0000000..a06e898
--- /dev/null
+++ b/examples/example_3.hsf
@@ -0,0 +1,30 @@
+@analyze_option{
+ loggers = [graphic=svg];
+ goal = WeakPass
+}
+@message{
+ m(Integer,Integer);
+ bip;bop;boop
+}
+@variable{
+ x : Integer;
+ y : Integer;
+ v : Integer;
+ w : Integer
+}
+@lifeline{
+ l1;
+ l2
+}
+@init{
+ l1.v = #;
+ l1.w = #
+}
+@seq(
+ l1 -- m(#,(v+w)) -> l2{x:=($0+$1);y:=($0-$1)},
+ @alt(
+ [(x>(y-2))]l2 -- bip -> l1,
+ [(x<=(y-2))]l2 -- bop -> l1
+ ),
+ l2 -- boop ->|
+)
\ No newline at end of file
diff --git a/examples/example_3_fail_param.htf b/examples/example_3_fail_param.htf
new file mode 100644
index 0000000..a5b8c7d
--- /dev/null
+++ b/examples/example_3_fail_param.htf
@@ -0,0 +1,4 @@
+{
+ [l1] l1!m(13,55);
+ [l2] l2?m(24,55).l2!bip
+}
\ No newline at end of file
diff --git a/examples/example_3_fail_path.htf b/examples/example_3_fail_path.htf
new file mode 100644
index 0000000..2ec637b
--- /dev/null
+++ b/examples/example_3_fail_path.htf
@@ -0,0 +1,4 @@
+{
+ [l1] l1!m(13,55);
+ [l2] l2?m(13,55).l2!bop
+}
\ No newline at end of file
diff --git a/examples/example_3_wpass.htf b/examples/example_3_wpass.htf
new file mode 100644
index 0000000..537fb87
--- /dev/null
+++ b/examples/example_3_wpass.htf
@@ -0,0 +1,4 @@
+{
+ [l1] l1!m(13,55);
+ [l2] l2?m(13,55).l2!bip
+}
\ No newline at end of file
diff --git a/examples/example_4.hsf b/examples/example_4.hsf
new file mode 100644
index 0000000..77d85e8
--- /dev/null
+++ b/examples/example_4.hsf
@@ -0,0 +1,24 @@
+@explore_option{
+ loggers = [graphic=svg]
+}
+@analyze_option{
+ loggers = [graphic=svg];
+ strategy = DFS;
+ goal = WeakPass
+}
+@message{
+ m(Integer)
+}
+@variable{
+ x : Integer;
+ y : Integer
+}
+@lifeline{
+ l1;
+ l2
+}
+@loop_seq(
+ @scope{x}(
+ {x:=#}l1 -- m(x) -> l2{y:=$0}
+ )
+)
\ No newline at end of file
diff --git a/examples/example_4.htf b/examples/example_4.htf
new file mode 100644
index 0000000..a7994ee
--- /dev/null
+++ b/examples/example_4.htf
@@ -0,0 +1,4 @@
+{
+ [l1] l1!m(3).l1!m(55).l1!m(37);
+ [l2] l2?m(3).l2?m(55)
+}
\ No newline at end of file
diff --git a/src/SymbexServices.proto b/src/SymbexServices.proto
new file mode 100644
index 0000000..e8f8cd1
--- /dev/null
+++ b/src/SymbexServices.proto
@@ -0,0 +1,345 @@
+/*******************************************************************************
+ * Copyright (c) 2020 CEA LIST.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ *
+ * Created on: 23 avr. 2020
+ *
+ * Contributors:
+ * Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
+ * Erwan Mahe (CentraleSUpelec) erwan.mahe@student.ecp.fr
+ * - Initial API and Implementation
+ ******************************************************************************/
+
+syntax = "proto3";
+
+option java_multiple_files = true;
+option java_package = "io.grpc.examples.helloworld";
+option java_outer_classname = "HelloWorldProto";
+option objc_class_prefix = "HLW";
+
+//import "google/protobuf/empty.proto";
+
+package sep.grpc;
+
+
+// The DIVERSITY/SYMBEX service definition.
+service Symbex {
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Initialization
+ rpc initialization (InitializationRequest) returns (InitializationReply) {}
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Model Parsing
+ rpc modelParse (ModelDefinitionRequest) returns (ModelParseReply) {}
+
+ rpc modelParseFile (ModelDefinitionRequest) returns (ModelParseReply) {}
+
+ // Model Parsing for Raw Textual
+ rpc modelParseText (ModelDefinitionRequest) returns (ModelParseReply) {}
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Model Evaluation
+ rpc modelEval (ModelDefinitionRequest) returns (ModelEvalReply) {}
+
+ ////////////////////////////////////////////////////////////////////////////
+ // SYMBEX
+
+ // Symbex Evaluation Initialization
+ rpc symbexEvalInit (SymbexEvalInitRequest) returns (SymbexEvalInitReply) {}
+
+ // Symbex Step
+ rpc symbexEvalStep (SymbexEvalStepRequest) returns (SymbexEvalStepReply) {}
+
+ // Symbex Evaluation
+ rpc symbexEvalContext (SymbexEvalContextRequest) returns (SymbexEvalStepReply) {}
+
+ // Symbex Evaluation of a Machine (by a string FQN_ID) on a symbolic Execution Context
+ rpc symbexEvalMachine (SymbexEvalRunnableRequest) returns (SymbexEvalRunnableReply) {}
+
+ // Symbex Evaluation of a Machine (by a string FQN_ID) on a Symbex Context
+ rpc symbexEvalBasicMachine (SymbexEvalRunnableRequest) returns (SymbexEvalRunnableBasicReply) {}
+
+ // Symbex Evaluation of a State (by a string FQN_ID) on a Symbex Context
+ rpc symbexEvalState (SymbexEvalRunnableRequest) returns (SymbexEvalRunnableReply) {}
+
+ // Symbex Evaluation of a Transition (by a string FQN_ID) on a Context
+ rpc symbexEvalTransition (SymbexEvalRunnableRequest) returns (SymbexEvalRunnableReply) {}
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // QUERY
+
+ // Symbex Query Variable Value
+ rpc queryValueofVariable (QueryValueForVariableRequest) returns (QueryValueForVariableReply) {}
+
+ // Symbex Query Trace for Condition
+ rpc queryNodeCondition (QueryValueForVariableRequest) returns (QueryValueForVariableReply) {}
+ rpc queryPathCondition (QueryValueForVariableRequest) returns (QueryValueForVariableReply) {}
+
+ // Symbex Query Trace for IO élement (input / output / newfresh)
+ rpc queryTraceIO(QueryValueForVariableRequest) returns (QueryValueForVariableReply) {}
+
+ // Symbex Query Trace for Executable element (machine / statemachine / state / transition)
+ rpc queryTraceExecutable (QueryValueForVariableRequest) returns (QueryValueForVariableReply) {}
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // POST PROCESSING
+
+ rpc runPostProcessor (PostProcessingRequest) returns (PostProcessingReply) {}
+
+}
+
+
+// **********
+// EXPRESSION ENCODING
+enum OperatorKind {
+ NOP = 0;
+
+ // additive op
+ ADD = 1;
+ MINUS = 2;
+ UMINUS = 3;
+
+ // multiplicative op
+ MULT = 4;
+ DIV = 5;
+
+ // logical op
+ OR = 6;
+ AND = 7;
+ NOT = 9;
+
+ // relationnal op
+ EQ = 10;
+ NEQ = 11;
+ GT = 12;
+ GTE = 13;
+ LT = 14;
+ LTE = 15;
+
+ // other op
+ NEWFRESH = 16;
+}
+
+message Expression {
+ oneof expression_alt {
+ // ***
+ // variable ID like a Fully Qualifed Name (FQN)
+ string variable_id = 1;
+ // ***
+ // symbol for symbolic parameterID like a Fully Qualifed Name (FQN)
+ string symbol_id = 2;
+ // ***
+ // operation for sub expression
+ Operation operation = 3;
+ // ***
+ // builtin raw expression
+ bool raw_bool = 4;
+ int64 raw_integer = 5;
+ double raw_float = 6;
+ string raw_string = 7;
+ }
+}
+
+message Operation {
+ OperatorKind operatorKind = 1;
+ repeated Expression operand = 2;
+}
+
+// **********
+// VARIABLE VALUE TRANSMISSION
+message VariableValuePair {
+ string variable_id = 1;
+ Expression value = 2;
+}
+// **********
+
+// **********
+// TYPED SYMBOL
+enum DataType {
+ ANY = 0;
+
+ BOOLEAN = 1;
+
+ INTEGER = 2;
+ RATIONAL = 3;
+ FLOAT = 4;
+
+ STRING = 5;
+
+ UNKNOWN = 6;
+}
+
+message TypedSymbol {
+ string symbol_id = 1;
+ DataType type = 2;
+}
+// **********
+
+
+// **********
+// The request / reply messages for Initialization.
+message InitializationRequest {
+ string session_id = 1;
+}
+
+message InitializationReply {
+ string message = 1;
+}
+// **********
+
+// **********
+// The request for model definition.
+// string field for file path location or full raw text model or workflow
+message ModelDefinitionRequest {
+ oneof model_alt {
+ // Model file path
+ string model_file_path = 1;
+ // Model raw text
+ string model_raw_text = 2;
+ }
+
+ oneof workflow_alt {
+ // Model file path
+ string workflow_file_path = 3;
+ // Model raw text
+ string workflow_raw_text = 4;
+ }
+}
+// **********
+
+// **********
+// The request / reply messages for Model Parsing.
+message ModelParseReply {
+ uint32 error_count = 1;
+ uint32 warning_count = 2;
+ repeated string error = 3;
+}
+// **********
+
+
+// **********
+// The request / reply messages for Model Evaluation.
+message ModelEvalReply {
+ ModelParseReply parse_reply = 1;
+
+ uint32 execution_context_count = 2;
+ uint32 execution_context_root_id = 3;
+
+ repeated uint32 not_yet_eval_execution_context_id = 4;
+
+ uint32 step_count = 5;
+ uint32 eval_count = 6;
+
+ uint32 max_execution_context_height = 7;
+ uint32 max_execution_context_width = 8;
+
+ uint32 redundancy_count = 9;
+ uint32 exit_execution_context_count = 10;
+ bool eval_limit_reached = 11;
+}
+// **********
+
+
+// **********
+// The request / reply messages for Symbex initialization
+message SymbexEvalInitRequest {
+ repeated VariableValuePair variable_value = 1;
+}
+
+message SymbexEvalInitReply {
+ uint32 execution_context_id = 1;
+ repeated VariableValuePair variable_value = 2;
+}
+// **********
+
+
+// **********
+// The request / reply messages for some Evaluation step
+message SymbexEvalStepRequest {
+ uint32 step_count = 1;
+ repeated VariableValuePair variable_value = 2;
+}
+
+message SymbexEvalStepReply {
+ uint32 step_count = 1;
+ uint32 eval_count = 2;
+
+ repeated uint32 not_yet_eval_execution_context_id = 3;
+}
+// **********
+
+// **********
+// The request / reply messages for Evaluation of a Context (by a integer ID)
+message SymbexEvalContextRequest {
+ uint32 execution_context_id = 1;
+ uint32 step_count = 2;
+ repeated VariableValuePair variable_value = 3;
+}
+
+
+
+// **********
+// The request / reply message for Evaluation of a Machine / State / Transtion
+// (by a string as Fully Qualified NameID) in the context of a symbeolic Execution Context
+message SymbexEvalRunnableRequest {
+ uint32 execution_context_id = 1;
+ string runnable_element_id = 2;
+ repeated VariableValuePair variable_value = 3;
+}
+
+message SymbexEvalRunnableReply {
+ repeated uint32 execution_context_id = 1;
+ repeated uint32 not_yet_eval_execution_context_id = 2;
+}
+
+message SymbexEvalRunnableBasicReply {
+ bool is_satisfiable = 1;
+ uint32 execution_context_id = 2;
+
+ Expression path_condition = 3;
+ Expression other_condition = 4;
+
+ repeated TypedSymbol created_symbols = 5;
+
+ repeated uint32 not_yet_eval_execution_context_id = 6;
+}
+// **********
+
+
+// **********
+// The request / reply message for Query on Symbex Context : value of a variable
+message QueryValueForVariableRequest {
+ uint32 execution_context_id = 1;
+ repeated string variable_id = 2;
+}
+
+message QueryValueForVariableReply {
+ uint32 execution_context_id = 1;
+ repeated VariableValuePair variable_value = 2;
+}
+// **********
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// POST PROCESSING
+
+ // **********
+// The request / reply message for Query on Symbex Context : value of a variable
+message PostProcessingRequest {
+ bool enable_execution_graph = 1;
+}
+
+message PostProcessingReply {
+ string execution_graph = 1;
+}
+// **********
+
+
diff --git a/src/core/context/execution.rs b/src/core/context/execution.rs
new file mode 100644
index 0000000..23da88e
--- /dev/null
+++ b/src/core/context/execution.rs
@@ -0,0 +1,280 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::{HashSet,HashMap};
+use std::collections::btree_map::BTreeMap;
+
+// ***
+
+use crate::core::context::general::GeneralContext;
+use crate::core::syntax::action::*;
+use crate::core::syntax::interaction::*;
+use crate::core::trace::{TraceAction,TraceActionKind};
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::builtin::bool::*;
+use crate::core::syntax::data::builtin::integer::*;
+use crate::core::syntax::data::builtin::float::*;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::builtin::string::*;
+use crate::core::syntax::data::var_ref::VariableReference;
+
+use crate::core::semantics::varmap::VarMapAble;
+
+use crate::core::error::HibouCoreError;
+
+
+#[derive(Clone, PartialEq, Debug)]
+pub struct ExecutionContext {
+ symbol_counter : usize,
+ symbol_types : BTreeMap<usize,TD_DataType>,
+ symbol_diversity_names : BTreeMap<usize,String>,
+ diversity_symbols_reverse_map : BTreeMap<String,usize>,
+ // ********** ********** ********** ********** ********** ********** **********
+ vr_id_counter : usize,
+ vr_originals : BTreeMap<usize,(usize,u32)>, // key is the unique ID
+ // first arg is the vr_id of the parent variable of which the current is an instance
+ // second arg is the instance number
+ vr_instances_count : BTreeMap<usize,u32>,
+ active_clocks : HashSet<usize>,
+ // ********** ********** ********** ********** ********** ********** **********
+ interpretation : BTreeMap<usize, BTreeMap<usize,TD_Generic> >, // key is the lifeline
+ // arg is mapping to current value
+ path_condition : TD_Bool
+}
+
+impl ExecutionContext {
+
+ pub fn get_path_condition(&self) -> &TD_Bool {
+ return &self.path_condition;
+ }
+
+ pub fn set_path_condition(&mut self, new_path_condition : TD_Bool) {
+ self.path_condition = new_path_condition;
+ }
+
+ pub fn get_lf_interpretation(&self, lf_id : usize) -> Option< &BTreeMap<usize,TD_Generic> > {
+ return self.interpretation.get(&lf_id);
+ }
+
+ pub fn set_lf_interpretation(&mut self, lf_id : usize, new_lf_interpretation : BTreeMap<usize,TD_Generic>) {
+ self.interpretation.insert( lf_id, new_lf_interpretation);
+ }
+
+ pub fn new(gen_ctx : &GeneralContext,interpretation:BTreeMap<usize, BTreeMap<usize,TD_Generic> >,symbol_counter:usize) -> ExecutionContext {
+ return ExecutionContext{
+ symbol_counter:symbol_counter,
+ symbol_types:BTreeMap::new(),
+ symbol_diversity_names:BTreeMap::new(),
+ diversity_symbols_reverse_map:BTreeMap::new(),
+ vr_id_counter:gen_ctx.get_vr_num(),
+ vr_originals:BTreeMap::new(),
+ vr_instances_count:BTreeMap::new(),
+ active_clocks : gen_ctx.get_clocks().clone(),
+ interpretation:interpretation,
+ path_condition:TD_Bool::TRUE
+ }
+ }
+
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+
+
+
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+
+ pub fn get_vr_num(&self) -> usize {
+ return self.vr_id_counter;
+ }
+
+ pub fn get_active_clocks(&self) -> &HashSet<usize> {
+ return &self.active_clocks;
+ }
+
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+
+ pub fn get_lf_name(&self, gen_ctx : &GeneralContext, lf_id : usize) -> Result<String,HibouCoreError> {
+ return gen_ctx.get_lf_name(lf_id);
+ }
+
+ pub fn get_ms_name(&self, gen_ctx : &GeneralContext, ms_id : usize) -> Result<String,HibouCoreError> {
+ return gen_ctx.get_ms_name(ms_id);
+ }
+
+ pub fn get_vr_parent_name_and_child_id(&self, gen_ctx: &GeneralContext, vr_id: usize) -> Result<(String, u32), HibouCoreError> {
+ if vr_id < gen_ctx.get_vr_num() {
+ return Ok((gen_ctx.get_vr_name(vr_id).unwrap(), 0));
+ } else {
+ match self.vr_originals.get(&vr_id) {
+ None => {
+ return Err(HibouCoreError::UnknownParameter(vr_id));
+ }
+ Some((parent_vr_id, instance_number)) => {
+ let parent_vr_name = gen_ctx.get_vr_name(*parent_vr_id).unwrap();
+ return Ok((parent_vr_name, *instance_number));
+ }
+ }
+ }
+ }
+
+ pub fn get_vr_name(&self, gen_ctx : &GeneralContext, vr_id : usize) -> Result<String,HibouCoreError> {
+ if vr_id < gen_ctx.get_vr_num() {
+ return gen_ctx.get_vr_name(vr_id);
+ } else {
+ match self.vr_originals.get(&vr_id ) {
+ None => {
+ return Err( HibouCoreError::UnknownParameter(vr_id) );
+ }
+ Some( (parent_vr_id,instance_number) ) => {
+ let parent_vr_name = gen_ctx.get_vr_name(*parent_vr_id).unwrap();
+ return Ok( format!("{}_{:}", parent_vr_name, instance_number) );
+ }
+ }
+ }
+ }
+
+ pub fn get_vr_type(&self, gen_ctx: &GeneralContext, vr_id: usize) -> Result<TD_DataType, HibouCoreError> {
+ if vr_id < gen_ctx.get_vr_num() {
+ return gen_ctx.get_vr_type(vr_id);
+ } else {
+ match self.vr_originals.get(&vr_id) {
+ None => {
+ return Err(HibouCoreError::UnknownParameter(vr_id));
+ }
+ Some((parent_vr_id, instance_number)) => {
+ let parent_vr_type = gen_ctx.get_vr_type(*parent_vr_id).unwrap();
+ return Ok(parent_vr_type);
+ }
+ }
+ }
+ }
+
+ pub fn is_clock(&self, gen_ctx: &GeneralContext, vr_id: usize) -> Result<bool, HibouCoreError> {
+ if vr_id < gen_ctx.get_vr_num() {
+ return Ok( gen_ctx.is_clock(vr_id) );
+ } else {
+ match self.vr_originals.get(&vr_id) {
+ None => {
+ return Err(HibouCoreError::UnknownParameter(vr_id));
+ }
+ Some((parent_vr_id, instance_number)) => {
+ let parent_is_clock = gen_ctx.is_clock(*parent_vr_id);
+ return Ok( parent_is_clock );
+ }
+ }
+ }
+ }
+
+
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+
+ pub fn add_diversity_symbol(&mut self, sy_fqn : &String, sy_type : &TD_DataType) -> usize {
+ let new_symbol_id = self.symbol_counter;
+ self.symbol_counter = self.symbol_counter +1;
+ self.symbol_diversity_names.insert( new_symbol_id, sy_fqn.clone());
+ self.diversity_symbols_reverse_map.insert( sy_fqn.clone(), new_symbol_id );
+ self.symbol_types.insert( new_symbol_id, sy_type.clone());
+ return new_symbol_id;
+ }
+
+ pub fn get_sy_diversity_name(&self, sy_id: usize) -> Result<String, HibouCoreError> {
+ match self.symbol_diversity_names.get(&sy_id) {
+ None => {
+ return Err( HibouCoreError::UnknownSymbol(Some(sy_id),None) );
+ },
+ Some(sy_diversity_name) => {
+ return Ok(sy_diversity_name.clone());
+ }
+ }
+ }
+
+ pub fn get_sy_type(&self, sy_id : usize) -> Result<TD_DataType,HibouCoreError> {
+ match self.symbol_types.get(&sy_id) {
+ None => {
+ return Err( HibouCoreError::UnknownSymbol(Some(sy_id),None) );
+ },
+ Some( sy_type ) => {
+ return Ok( sy_type.clone() );
+ }
+ }
+ }
+
+ pub fn get_sy_type_from_fqn(&self, sy_fqn : &String) -> Result<TD_DataType,HibouCoreError> {
+ match self.diversity_symbols_reverse_map.get(sy_fqn) {
+ None => {
+ return Err( HibouCoreError::UnknownSymbol(None,Some(sy_fqn.clone()) ) );
+ },
+ Some( sy_id ) => {
+ return self.get_sy_type(*sy_id);
+ }
+ }
+ }
+
+ pub fn get_sy_id_from_fqn(&self, sy_fqn : &String) -> Result<usize,HibouCoreError> {
+ match self.diversity_symbols_reverse_map.get(sy_fqn) {
+ None => {
+ return Err( HibouCoreError::UnknownSymbol(None,Some(sy_fqn.clone()) ) );
+ },
+ Some( sy_id ) => {
+ return Ok(*sy_id);
+ }
+ }
+ }
+
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+
+ fn create_variable_instance(&mut self, parent_vr_id : usize) -> usize {
+ let new_vr_instance_num : u32;
+ match self.vr_instances_count.get(&parent_vr_id) {
+ None => {
+ new_vr_instance_num = 1;
+ },
+ Some( instance_num ) => {
+ new_vr_instance_num = *instance_num;
+ }
+ }
+ self.vr_instances_count.insert(parent_vr_id, new_vr_instance_num+1 );
+ // ***
+ let new_vr_unique_id = self.vr_id_counter;
+ self.vr_id_counter = self.vr_id_counter +1;
+ self.vr_originals.insert(new_vr_unique_id, (parent_vr_id, new_vr_instance_num));
+ return new_vr_unique_id;
+ }
+
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+
+ pub fn open_scope(&mut self, gen_ctx : &GeneralContext, scope : &Vec<usize>, interaction : &Interaction) -> Interaction {
+ let mut mapping : HashMap<usize,usize> = HashMap::new();
+ for vr_id in scope {
+ let new_vr_id = self.create_variable_instance(*vr_id);
+ mapping.insert(*vr_id,new_vr_id);
+ if self.is_clock(gen_ctx,*vr_id).unwrap() {
+ self.active_clocks.insert(new_vr_id);
+ }
+ }
+ return interaction.apply_variable_mapping(&mapping);
+ }
+
+}
+
diff --git a/src/core/context/general.rs b/src/core/context/general.rs
new file mode 100644
index 0000000..dd7a9f8
--- /dev/null
+++ b/src/core/context/general.rs
@@ -0,0 +1,254 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashSet;
+
+use crate::core::syntax::data::td_type::TD_DataType;
+
+use crate::core::error::HibouCoreError;
+
+#[derive(Clone, PartialEq, Debug)]
+pub struct GeneralContext {
+ lf_groups : Vec<String>,
+ lf_names : Vec<String>,
+ ms_specs : Vec< (String,Vec<(TD_DataType,Option<String>)>) >,
+ vr_names : Vec<String>,
+ vr_types : Vec<TD_DataType>,
+ clocks : HashSet<usize>
+}
+
+
+
+impl GeneralContext {
+
+ pub fn new() -> GeneralContext {
+ return GeneralContext{
+ lf_groups:Vec::new(),
+ lf_names:Vec::new(),
+ ms_specs:Vec::new(),
+ vr_names:Vec::new(),
+ vr_types:Vec::new(),
+ clocks:HashSet::new()};
+ }
+
+ pub fn get_lf_names(&self) -> &Vec<String> {
+ return &self.lf_names;
+ }
+
+ pub fn get_vr_names(&self) -> &Vec<String> {
+ return &self.vr_names;
+ }
+
+ pub fn get_vr_types(&self) -> &Vec<TD_DataType> {
+ return &self.vr_types;
+ }
+
+ pub fn get_ms_specs(&self) -> &Vec<(String, Vec<(TD_DataType, Option<String>)>)> {
+ return &self.ms_specs;
+ }
+
+ pub fn get_clocks(&self) -> &HashSet<usize> {
+ return &self.clocks;
+ }
+
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+
+ pub fn add_as_clock(&mut self, vr_id : usize) {
+ self.clocks.insert(vr_id);
+ }
+
+ pub fn add_lf_group(&mut self, lgr_name : String) -> usize {
+ match self.get_lf_id( &lgr_name ) {
+ None => {
+ match self.get_lgr_id(&lgr_name) {
+ None => {
+ self.lf_groups.push(lgr_name );
+ return self.lf_groups.len() - 1;
+ },
+ Some(lgr_id) => {
+ return lgr_id;
+ }
+ }
+ },
+ _ => {
+ panic!("trying to add a group with same name as a known lifeline");
+ }
+ }
+ }
+
+ pub fn add_lf(&mut self, lf_name : String) -> usize {
+ match self.get_lgr_id( &lf_name ) {
+ None => {
+ match self.get_lf_id(&lf_name) {
+ None => {
+ self.lf_names.push(lf_name);
+ return self.lf_names.len() - 1;
+ },
+ Some(lf_id) => {
+ return lf_id;
+ }
+ }
+ },
+ _ => {
+ panic!("trying to add a lifeline with same name as a known group");
+ }
+ }
+ }
+
+ pub fn add_msg(&mut self, ms_name : String, ms_spec : Vec<(TD_DataType,Option<String>)>) -> usize {
+ for (got_ms_name,got_ms_spec) in &self.ms_specs {
+ if got_ms_name == &ms_name {
+ panic!();
+ }
+ }
+ self.ms_specs.push( (ms_name, ms_spec) );
+ return self.ms_specs.len() - 1;
+ }
+
+ pub fn add_vr(&mut self, vr_name : String, vr_type : TD_DataType) {
+ self.vr_names.push(vr_name);
+ self.vr_types.push(vr_type);
+ }
+
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+
+ pub fn get_lgr_id(&self, lgr_name : &str) -> Option<usize> {
+ return self.lf_groups.iter().position(|gn| gn == lgr_name);
+ }
+
+ pub fn get_lf_id(&self, lf_name : &str) -> Option<usize> {
+ return self.lf_names.iter().position(|r| r == lf_name);
+ }
+
+ pub fn get_vr_id(&self, vr_name : &str) -> Option<usize> {
+ return self.vr_names.iter().position(|r| r == vr_name);
+ }
+
+ pub fn get_ms_id(&self, ms_name : &str) -> Option<usize> {
+ return self.ms_specs.iter().position(|(n,s)| n == ms_name);
+ }
+
+ pub fn is_clock(&self, vr_id : usize) -> bool {
+ return self.clocks.contains( &vr_id );
+ }
+
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+
+ pub fn get_lf_num(&self) -> usize {
+ return self.lf_names.len();
+ }
+
+ pub fn get_ms_num(&self) -> usize {
+ return self.ms_specs.len();
+ }
+
+ pub fn get_vr_num(&self) -> usize {
+ return self.vr_names.len();
+ }
+
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+ // ********** ********** ********** ********** ********** ********** **********
+
+ pub fn get_lgr_name(&self, lgr_id : usize) -> Result<String,HibouCoreError> {
+ match self.lf_groups.get(lgr_id) {
+ None => {
+ return Err( HibouCoreError::UnknownLifelineGroup(lgr_id) );
+ },
+ Some( got_str ) => {
+ return Ok( got_str.to_string() );
+ }
+ }
+ }
+
+ pub fn get_lf_name(&self, lf_id : usize) -> Result<String,HibouCoreError> {
+ match self.lf_names.get(lf_id) {
+ None => {
+ return Err( HibouCoreError::UnknownLifeline(lf_id) );
+ },
+ Some( got_str ) => {
+ return Ok( got_str.to_string() );
+ }
+ }
+ }
+
+ pub fn get_ms_name(&self, ms_id : usize) -> Result<String,HibouCoreError> {
+ match self.ms_specs.get(ms_id) {
+ None => {
+ return Err( HibouCoreError::UnknownMessage(ms_id) );
+ },
+ Some( (ms_name, ms_spec) ) => {
+ return Ok( ms_name.to_string() );
+ }
+ }
+ }
+
+ pub fn get_ms_spec(&self, ms_id : usize) -> Result<Vec<(TD_DataType,Option<String>)>,HibouCoreError> {
+ match self.ms_specs.get(ms_id) {
+ None => {
+ return Err( HibouCoreError::UnknownMessage(ms_id) );
+ },
+ Some( (ms_name, ms_spec) ) => {
+ return Ok( ms_spec.clone() );
+ }
+ }
+ }
+
+ pub fn get_pr_type(&self, ms_id : usize, pr_id : usize) -> Result<TD_DataType,HibouCoreError> {
+ match self.ms_specs.get(ms_id) {
+ None => {
+ return Err( HibouCoreError::UnknownMessage(ms_id) );
+ },
+ Some( (ms_name, ms_spec) ) => {
+ match ms_spec.get(pr_id) {
+ None => {
+ return Err( HibouCoreError::UnknownParameter(pr_id) );
+ },
+ Some( (pr_type,opt_pr_name) ) => {
+ return Ok(pr_type.clone());
+ }
+ }
+ }
+ }
+ }
+
+ pub fn get_vr_name(&self, vr_id : usize) -> Result<String,HibouCoreError> {
+ match self.vr_names.get(vr_id) {
+ None => {
+ return Err( HibouCoreError::UnknownParameter(vr_id) );
+ },
+ Some(my_str) => {
+ return Ok( my_str.to_string() )
+ }
+ }
+ }
+
+ pub fn get_vr_type(&self, vr_id : usize) -> Result<TD_DataType,HibouCoreError> {
+ match self.vr_types.get(vr_id) {
+ None => {
+ return Err( HibouCoreError::UnknownParameter(vr_id) );
+ },
+ Some(my_type) => {
+ return Ok( my_type.clone() )
+ }
+ }
+ }
+
+}
diff --git a/src/core/context/mod.rs b/src/core/context/mod.rs
new file mode 100644
index 0000000..8c1023d
--- /dev/null
+++ b/src/core/context/mod.rs
@@ -0,0 +1,16 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod general;
+pub mod execution;
\ No newline at end of file
diff --git a/src/core/error.rs b/src/core/error.rs
new file mode 100644
index 0000000..0eba9cc
--- /dev/null
+++ b/src/core/error.rs
@@ -0,0 +1,108 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::fmt;
+
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::interaction::Interaction;
+use crate::core::syntax::position::Position;
+
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+
+
+use crate::diversity::*;
+
+
+#[derive(Debug)]
+pub enum HibouCoreError {
+ PruningError,
+ PositionError(Interaction,Position),
+ UnknownLifelineGroup(usize),
+ UnknownLifeline(usize),
+ UnknownMessage(usize),
+ UnknownParameter(usize),
+ UnknownSymbol(Option<usize>,Option<String>),
+ UninterpretedVariable(usize),
+ UninterpretedParameter(usize,usize),
+ WronglyTypedExpression(TD_Generic,TD_DataType),
+ WronglyTypedGrpcInputOperation(Operation),
+ WronglyTypedGrpcInput(String, TD_DataType, String),
+ UnknownOperatorInGrpcInputOperation(Operation),
+ SolverUnknownSatisfiability
+}
+
+impl fmt::Display for HibouCoreError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ HibouCoreError::PruningError => {
+ return write!(f, "{}", format!("error while pruning"));
+ },
+ HibouCoreError::PositionError(interaction, position) => {
+ return write!(f, "{}", format!("position {:?} is not a leaf of {:?}", position, interaction));
+ },
+ HibouCoreError::UnknownLifelineGroup( lgr_id ) => {
+ return write!(f, "{}", format!("context error ; unknown lifeline group : {:}", lgr_id));
+ },
+ HibouCoreError::UnknownLifeline( lf_id ) => {
+ return write!(f, "{}", format!("context error ; unknown lifeline : {:}", lf_id));
+ },
+ HibouCoreError::UnknownMessage( ms_id ) => {
+ return write!(f, "{}", format!("context error ; unknown message : {:}", ms_id));
+ },
+ HibouCoreError::UnknownParameter( vr_id ) => {
+ return write!(f, "{}", format!("context error ; unknown parameter : {:}", vr_id));
+ },
+ HibouCoreError::UnknownSymbol( sy_id_opt, sy_fqn_opt ) => {
+ match sy_id_opt {
+ None => {
+ match sy_fqn_opt {
+ None => {
+ panic!();
+ },
+ Some( sy_fqn ) => {
+ return write!(f, "{}", format!("context error ; unknown symbol fqn : {:}", sy_fqn));
+ }
+ }
+ },
+ Some(sy_id) => {
+ return write!(f, "{}", format!("context error ; unknown symbol id : {:}", sy_id));
+ }
+ }
+ },
+ HibouCoreError::UninterpretedVariable( vr_id ) => {
+ return write!(f, "{}", format!("context error ; uninterpreted variable : {:}", vr_id));
+ },
+ HibouCoreError::UninterpretedParameter( ms_id, pr_id ) => {
+ return write!(f, "{}", format!("context error ; uninterpreted parameter {:} on message {:}", pr_id, ms_id));
+ },
+ HibouCoreError::WronglyTypedExpression( expr, expected_type ) => {
+ return write!(f, "{}", format!("context error ; parameter : wrongly typed expression : {:?} - expected : {:?}", expr, expected_type));
+ },
+ HibouCoreError::WronglyTypedGrpcInputOperation( operation ) => {
+ return write!(f, "{}", format!("grpc input error on operation : {:?}", operation));
+ },
+ HibouCoreError::WronglyTypedGrpcInput( input_as_str, expected_type, interpreted_type ) => {
+ return write!(f, "{}", format!("grpc input error in '{:?}' - expected '{:?}' - got '{:?}'", input_as_str, expected_type, interpreted_type ));
+ },
+ HibouCoreError::UnknownOperatorInGrpcInputOperation( operation ) => {
+ return write!(f, "{}", format!("unknown grpc operator : {:?}", operation));
+ },
+ HibouCoreError::SolverUnknownSatisfiability => {
+ return write!(f, "{}", format!("solver returned Unknown"));
+ }
+ }
+ }
+}
diff --git a/src/core/mod.rs b/src/core/mod.rs
new file mode 100644
index 0000000..194b468
--- /dev/null
+++ b/src/core/mod.rs
@@ -0,0 +1,21 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod syntax;
+pub mod context;
+pub mod semantics;
+pub mod error;
+
+pub mod trace;
+
diff --git a/src/core/semantics/frontier.rs b/src/core/semantics/frontier.rs
new file mode 100644
index 0000000..19a84bb
--- /dev/null
+++ b/src/core/semantics/frontier.rs
@@ -0,0 +1,92 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashSet;
+
+use crate::core::syntax::position::*;
+use crate::core::syntax::interaction::*;
+
+
+
+pub fn make_frontier(interaction : &Interaction) -> Vec<Position> {
+ match interaction {
+ &Interaction::Empty => {
+ return Vec::new();
+ },
+ &Interaction::Action(_) => {
+ return vec![Position::Epsilon];
+ },
+ &Interaction::Strict(ref i1, ref i2) => {
+ let mut front = push_frontier(&PositionKind::Left, make_frontier(i1));
+ if i1.express_empty() {
+ front.append( &mut push_frontier(&PositionKind::Right, make_frontier(i2)) )
+ }
+ return front;
+ },
+ &Interaction::Seq(ref i1, ref i2) => {
+ let mut front = push_frontier(&PositionKind::Left, make_frontier(i1));
+ for pos2 in push_frontier(&PositionKind::Right, make_frontier(i2)) {
+ let act = interaction.get_sub_interaction(&pos2 ).as_leaf();
+ if i1.avoids(act.lf_act.lf_id) {
+ front.push(pos2);
+ }
+ }
+ return front;
+ },
+ &Interaction::Alt(ref i1, ref i2) => {
+ let mut front = push_frontier(&PositionKind::Left, make_frontier(i1));
+ front.append( &mut push_frontier(&PositionKind::Right, make_frontier(i2)) );
+ return front;
+ },
+ &Interaction::Par(ref i1, ref i2) => {
+ let mut front = push_frontier(&PositionKind::Left, make_frontier(i1));
+ front.append( &mut push_frontier(&PositionKind::Right, make_frontier(i2)) );
+ return front;
+ },
+ &Interaction::Loop(_, ref i1) => {
+ return push_frontier(&PositionKind::Left, make_frontier(i1));
+ },
+ &Interaction::Scope(_, ref i1) => {
+ return push_frontier(&PositionKind::Left, make_frontier(i1));
+ }
+ }
+}
+
+
+
+enum PositionKind {
+ Left,
+ Right
+}
+
+fn push_frontier(pkind : &PositionKind, frontier : Vec<Position>) -> Vec<Position> {
+ let mut new_frontier : Vec<Position> = Vec::new();
+ // ***
+ for my_pos in frontier {
+ let new_pos : Position;
+ match pkind {
+ PositionKind::Left => {
+ new_pos = Position::Left( Box::new(my_pos ) );
+ },
+ PositionKind::Right => {
+ new_pos = Position::Right( Box::new(my_pos ) );
+ }
+ }
+ new_frontier.push( new_pos );
+ }
+ // ***
+ return new_frontier;
+}
+
+
diff --git a/src/core/semantics/mod.rs b/src/core/semantics/mod.rs
new file mode 100644
index 0000000..8166155
--- /dev/null
+++ b/src/core/semantics/mod.rs
@@ -0,0 +1,18 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod varmap;
+pub mod frontier;
+pub mod prune;
+pub mod shape_execute;
\ No newline at end of file
diff --git a/src/core/semantics/prune.rs b/src/core/semantics/prune.rs
new file mode 100644
index 0000000..2fc8038
--- /dev/null
+++ b/src/core/semantics/prune.rs
@@ -0,0 +1,62 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashSet;
+
+use crate::core::syntax::position::*;
+use crate::core::syntax::interaction::*;
+use crate::core::semantics::frontier::*;
+
+
+pub fn prune(my_int : &Interaction, lf_id : usize) -> Interaction {
+ match my_int {
+ Interaction::Empty => {
+ return Interaction::Empty;
+ },
+ Interaction::Action(ref act) => {
+ return Interaction::Action(act.clone());
+ },
+ Interaction::Seq(ref i1, ref i2) => {
+ return Interaction::Seq( Box::new( prune(i1,lf_id)), Box::new( prune(i2,lf_id)) );
+ },
+ Interaction::Strict(ref i1, ref i2) => {
+ return Interaction::Strict( Box::new( prune(i1,lf_id)), Box::new( prune(i2,lf_id)) );
+ },
+ Interaction::Par(ref i1, ref i2) => {
+ return Interaction::Par( Box::new( prune(i1,lf_id)), Box::new( prune(i2,lf_id)) );
+ },
+ Interaction::Alt(ref i1, ref i2) => {
+ if i1.avoids(lf_id) {
+ if i2.avoids(lf_id) {
+ return Interaction::Alt( Box::new( prune(i1,lf_id)), Box::new( prune(i2,lf_id)) );
+ } else {
+ return prune(i1,lf_id);
+ }
+ } else {
+ return prune(i2,lf_id);
+ }
+ },
+ Interaction::Loop(ref lkind, ref i1) => {
+ if i1.avoids(lf_id) {
+ return Interaction::Loop(lkind.clone(), Box::new(prune(i1,lf_id)));
+ } else {
+ return Interaction::Empty;
+ }
+ },
+ Interaction::Scope(sko, i1) => {
+ return Interaction::Scope(sko.clone(), Box::new(prune(i1,lf_id)));
+ }
+ }
+}
+
diff --git a/src/core/semantics/shape_execute.rs b/src/core/semantics/shape_execute.rs
new file mode 100644
index 0000000..37ec54e
--- /dev/null
+++ b/src/core/semantics/shape_execute.rs
@@ -0,0 +1,184 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::{HashSet,HashMap};
+
+
+
+use crate::core::syntax::position::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::interaction::*;
+
+use crate::core::semantics::frontier::*;
+use crate::core::semantics::prune::*;
+use crate::core::semantics::varmap::*;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+
+use crate::core::trace::*;
+use crate::core::error::HibouCoreError;
+
+pub fn shape_execute( gen_ctx : &GeneralContext,
+ exe_ctx : &mut ExecutionContext,
+ my_int : &Interaction,
+ my_pos : &Position)
+ -> Result< (Interaction,Position,ObservableAction,bool) , HibouCoreError > { // if events_to_match is None then we will use the usize index 0 for the execution result unconstrained by a trace action
+ // ***
+ let model_action = my_int.get_sub_interaction(my_pos).as_leaf();
+ // ***
+ return shape_execute_rec(gen_ctx,exe_ctx, my_int, &model_action.lf_act.lf_id, my_pos, &mut Vec::new());
+}
+
+
+
+
+
+fn shape_execute_left_in_schedule_operator( gen_ctx : &GeneralContext,
+ exe_ctx : &mut ExecutionContext,
+ my_i1 : &Interaction,
+ my_i2 : &Interaction,
+ concerned_lf : &usize,
+ my_sub_pos : &Position,
+ op_kind : &ScheduleOperatorKind,
+ current_position : &mut Vec<u32>) -> Result< (Interaction,Position,ObservableAction,bool) , HibouCoreError > {
+ current_position.push(1);
+ match shape_execute_rec(gen_ctx,exe_ctx, my_i1,concerned_lf,my_sub_pos, current_position) {
+ Err(e) => {return Err(e);}
+ Ok( (new_i1,final_pos,final_action,needs_scoping) ) => {
+ let boxed_i2 = Box::new( my_i2.clone() );
+ let final_interaction : Interaction;
+ match op_kind {
+ ScheduleOperatorKind::Strict => {
+ final_interaction = Interaction::Strict(Box::new(new_i1), boxed_i2);
+ },
+ ScheduleOperatorKind::Seq => {
+ final_interaction = Interaction::Seq(Box::new(new_i1), boxed_i2);
+ },
+ ScheduleOperatorKind::Par => {
+ final_interaction = Interaction::Par(Box::new(new_i1), boxed_i2);
+ }
+ }
+ return Ok( (final_interaction,final_pos,final_action,needs_scoping) );
+ }
+ }
+}
+
+
+
+fn shape_execute_rec(gen_ctx : &GeneralContext,
+ exe_ctx : &mut ExecutionContext,
+ my_int : &Interaction,
+ concerned_lf : &usize,
+ target_pos : &Position,
+ current_position : &mut Vec<u32>) -> Result< (Interaction,Position,ObservableAction,bool) , HibouCoreError > {
+ match target_pos {
+ Position::Epsilon => {
+ match my_int {
+ &Interaction::Action(ref model_action) => {
+ return Ok( (my_int.clone(),Position::from_vec(current_position),model_action.clone(),false) );
+ },
+ _ => {
+ return Err( HibouCoreError::PositionError(my_int.clone(), target_pos.clone()) );
+ }
+ }
+ },
+ Position::Left(sub_pos) => {
+ match my_int {
+ &Interaction::Alt(ref i1,_) => {
+ return shape_execute_rec(gen_ctx,exe_ctx, &*i1,concerned_lf,&*sub_pos,current_position);
+ },
+ &Interaction::Loop(ref lkind, ref i1) => {
+ return shape_execute_left_in_schedule_operator(gen_ctx,exe_ctx,&*i1, my_int, concerned_lf,&*sub_pos, lkind,current_position);
+ },
+ &Interaction::Scope(ref scope, ref i1) => {
+ let new_i1 = exe_ctx.open_scope(gen_ctx, scope, i1);
+ match shape_execute_rec(gen_ctx,exe_ctx, &new_i1, concerned_lf,&*sub_pos,current_position) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (final_interaction,final_pos,final_action,needs_scoping) ) => {
+ return Ok( (final_interaction,final_pos,final_action,true) );
+ }
+ }
+ },
+ &Interaction::Strict(ref i1,ref i2) => {
+ return shape_execute_left_in_schedule_operator(gen_ctx,exe_ctx,&*i1, &*i2, concerned_lf,&*sub_pos, &ScheduleOperatorKind::Strict,current_position);
+ },
+ &Interaction::Seq(ref i1,ref i2) => {
+ return shape_execute_left_in_schedule_operator(gen_ctx,exe_ctx,&*i1, &*i2, concerned_lf,&*sub_pos, &ScheduleOperatorKind::Seq,current_position);
+ },
+ &Interaction::Par(ref i1,ref i2) => {
+ return shape_execute_left_in_schedule_operator(gen_ctx,exe_ctx,&*i1, &*i2, concerned_lf,&*sub_pos, &ScheduleOperatorKind::Par,current_position);
+ },
+ _ => {
+ return Err( HibouCoreError::PositionError(my_int.clone(), target_pos.clone()) );
+ }
+ }
+ },
+ Position::Right(sub_pos) => {
+ match my_int {
+ &Interaction::Alt(_,ref i2) => {
+ return shape_execute_rec(gen_ctx,exe_ctx, &*i2,concerned_lf,&*sub_pos,current_position);
+ },
+ &Interaction::Strict(_,ref i2) => {
+ return shape_execute_rec(gen_ctx,exe_ctx, &*i2,concerned_lf,&*sub_pos,current_position);
+ },
+ &Interaction::Seq(ref i1,ref i2) => {
+ let new_i1 = prune(i1,*concerned_lf);
+ // ***
+ if new_i1 == Interaction::Empty {
+ match shape_execute_rec(gen_ctx,exe_ctx,&*i2, concerned_lf,&*sub_pos,current_position) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (new_i2,final_pos,final_action,needs_scoping) ) => {
+ return Ok( (new_i2,final_pos,final_action,needs_scoping) );
+ }
+ }
+ } else {
+ current_position.push(2);
+ match shape_execute_rec(gen_ctx,exe_ctx,&*i2, concerned_lf,&*sub_pos,current_position) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (new_i2,final_pos,final_action,needs_scoping) ) => {
+ let final_interaction = Interaction::Seq(Box::new(new_i1), Box::new(new_i2) );
+ return Ok( (final_interaction,final_pos,final_action,needs_scoping) );
+ }
+ }
+ }
+ },
+ &Interaction::Par(ref i1,ref i2) => {
+ current_position.push(2);
+ match shape_execute_rec(gen_ctx,exe_ctx,&*i2, concerned_lf,&*sub_pos,current_position) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (new_i2,final_pos,final_action,needs_scoping) ) => {
+ let final_interaction = Interaction::Par(i1.clone(), Box::new(new_i2) );
+ return Ok( (final_interaction,final_pos,final_action,needs_scoping) );
+ }
+ }
+ },
+ _ => {
+ return Err( HibouCoreError::PositionError(my_int.clone(), target_pos.clone()) );
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/core/semantics/varmap.rs b/src/core/semantics/varmap.rs
new file mode 100644
index 0000000..1f915c5
--- /dev/null
+++ b/src/core/semantics/varmap.rs
@@ -0,0 +1,190 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::{HashSet,HashMap};
+
+use crate::core::syntax::action::*;
+use crate::core::syntax::interaction::Interaction;
+
+pub trait VarMapAble {
+
+ fn apply_variable_mapping(&self, mapping : &HashMap<usize,usize>) -> Self;
+}
+
+
+// ********** ********** ********** ********** ********** ********** **********
+// ********** ********** ********** ********** ********** ********** **********
+// ********** ********** ********** ********** ********** ********** **********
+
+// For Interactions
+
+impl VarMapAble for Interaction {
+
+ fn apply_variable_mapping(&self, mapping : &HashMap<usize,usize>) -> Interaction {
+ match self {
+ &Interaction::Empty => {
+ return Interaction::Empty;
+ },
+ &Interaction::Action(ref act) => {
+ return Interaction::Action( act.apply_variable_mapping(mapping) );
+ },
+ &Interaction::Strict(ref i1, ref i2) => {
+ return Interaction::Strict(Box::new(i1.apply_variable_mapping(mapping)),
+ Box::new(i2.apply_variable_mapping(mapping)));
+ },
+ &Interaction::Seq(ref i1, ref i2) => {
+ return Interaction::Seq(Box::new(i1.apply_variable_mapping(mapping)),
+ Box::new(i2.apply_variable_mapping(mapping)));
+ },
+ &Interaction::Alt(ref i1, ref i2) => {
+ return Interaction::Alt(Box::new(i1.apply_variable_mapping(mapping)),
+ Box::new(i2.apply_variable_mapping(mapping)));
+ },
+ &Interaction::Par(ref i1, ref i2) => {
+ return Interaction::Par(Box::new(i1.apply_variable_mapping(mapping)),
+ Box::new(i2.apply_variable_mapping(mapping)));
+ },
+ &Interaction::Loop(ref lkind, ref i1) => {
+ return Interaction::Loop(lkind.clone(),
+ Box::new(i1.apply_variable_mapping(mapping)));
+ },
+ &Interaction::Scope(ref scoped_vr_ids, ref i1) => {
+ let mut new_vr_ids : Vec<usize> = Vec::new();
+ for vr_id in scoped_vr_ids {
+ match mapping.get(vr_id) {
+ None => {
+ new_vr_ids.push( *vr_id );
+ },
+ Some( new_vr_id ) => {
+ new_vr_ids.push( *new_vr_id );
+ }
+ }
+ }
+ return Interaction::Scope(new_vr_ids,
+ Box::new(i1.apply_variable_mapping(mapping)));
+ }
+ }
+ }
+}
+
+// ********** ********** ********** ********** ********** ********** **********
+// ********** ********** ********** ********** ********** ********** **********
+// ********** ********** ********** ********** ********** ********** **********
+
+// For Actions and contents
+
+impl VarMapAble for ActionAmbleItem {
+
+ fn apply_variable_mapping(&self, mapping : &HashMap<usize,usize>) -> ActionAmbleItem {
+ match self {
+ ActionAmbleItem::Guard( guard ) => {
+ return ActionAmbleItem::Guard( guard.apply_variable_mapping(mapping) );
+ },
+ ActionAmbleItem::Reset(vr_id) => {
+ match mapping.get(vr_id) {
+ None => {
+ return ActionAmbleItem::Reset(*vr_id);
+ },
+ Some( new_vr_id ) => {
+ return ActionAmbleItem::Reset(*new_vr_id);
+ }
+ }
+ },
+ ActionAmbleItem::Assignment(vr_id, valueornewfresh) => {
+ let new_vr_id : usize;
+ match mapping.get(vr_id) {
+ None => {
+ new_vr_id = *vr_id;
+ },
+ Some( npid ) => {
+ new_vr_id = *npid;
+ }
+ }
+ match valueornewfresh {
+ ValueOrNewFresh::Value( td_generic ) => {
+ return ActionAmbleItem::Assignment(new_vr_id,ValueOrNewFresh::Value(td_generic.apply_variable_mapping(mapping)));
+ },
+ ValueOrNewFresh::NewFresh => {
+ return ActionAmbleItem::Assignment(new_vr_id,ValueOrNewFresh::NewFresh);
+ }
+ }
+ }
+ }
+ }
+}
+
+impl VarMapAble for LifelineAction {
+
+ fn apply_variable_mapping(&self, mapping : &HashMap<usize,usize>) -> LifelineAction {
+ let mut preamble : Vec<ActionAmbleItem> = Vec::new();
+ for item in &self.preamble {
+ preamble.push( item.apply_variable_mapping(mapping) );
+ }
+ // ***
+ let mut postamble : Vec<ActionAmbleItem> = Vec::new();
+ for item in &self.postamble {
+ postamble.push( item.apply_variable_mapping(mapping) );
+ }
+ // ***
+ return LifelineAction{preamble,lf_id:self.lf_id,postamble};
+ }
+}
+
+
+impl VarMapAble for ObservableAction {
+
+ fn apply_variable_mapping(&self, mapping : &HashMap<usize,usize>) -> ObservableAction {
+ // ***
+ let new_lf_act = self.lf_act.apply_variable_mapping(mapping);
+ // ***
+ let new_act_kind :ObservableActionKind;
+ match &self.act_kind {
+ ObservableActionKind::Reception => {
+ new_act_kind = ObservableActionKind::Reception;
+ },
+ ObservableActionKind::Emission(targets) => {
+ let mut new_targets : Vec<LifelineAction> = Vec::new();
+ for lf_act in targets {
+ new_targets.push( lf_act.apply_variable_mapping(mapping) );
+ }
+ new_act_kind = ObservableActionKind::Emission(new_targets);
+ }
+ }
+ // ***
+ let mut new_params : Vec<ValueOrNewFresh> = Vec::new();
+ for par_arg in &self.params {
+ match par_arg {
+ ValueOrNewFresh::NewFresh => {
+ new_params.push( ValueOrNewFresh::NewFresh );
+ },
+ ValueOrNewFresh::Value( td_gen ) => {
+ new_params.push( ValueOrNewFresh::Value( td_gen.apply_variable_mapping(mapping) ));
+ }
+ }
+ }
+ // ***
+ return ObservableAction{
+ lf_act:new_lf_act,
+ act_kind:new_act_kind,
+ ms_id:self.ms_id,
+ params:new_params,
+ original_position:self.original_position.clone()
+ }
+ }
+}
+
+// ********** ********** ********** ********** ********** ********** **********
+// ********** ********** ********** ********** ********** ********** **********
+// ********** ********** ********** ********** ********** ********** **********
+
diff --git a/src/core/syntax/action.rs b/src/core/syntax/action.rs
new file mode 100644
index 0000000..4a07388
--- /dev/null
+++ b/src/core/syntax/action.rs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::fmt::Debug;
+use std::collections::HashSet;
+
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::core::syntax::data::generic::TD_Generic;
+
+use crate::core::trace::{TraceAction,TraceActionKind};
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum ValueOrNewFresh {
+ Value(TD_Generic),
+ NewFresh
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum ActionAmbleItem {
+ Guard(TD_Bool),
+ Assignment(usize, ValueOrNewFresh),
+ Reset(usize)
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub struct LifelineAction { // <T : Clone + PartialEq + Debug>
+ pub preamble : Vec<ActionAmbleItem>,
+ pub lf_id : usize, // T,
+ pub postamble : Vec<ActionAmbleItem>
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum ObservableActionKind {
+ Reception,
+ Emission(Vec<LifelineAction>)
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub struct ObservableAction {
+ pub lf_act : LifelineAction,
+ pub act_kind : ObservableActionKind,
+ pub ms_id : usize,
+ pub params : Vec<ValueOrNewFresh>,
+ pub original_position : Option<Vec<u32>>
+}
+
+
+impl ObservableAction {
+
+ pub fn get_action_kind(&self) -> TraceActionKind {
+ match self.act_kind {
+ ObservableActionKind::Reception => {
+ return TraceActionKind::Reception;
+ },
+ ObservableActionKind::Emission(_) => {
+ return TraceActionKind::Emission;
+ }
+ }
+ }
+
+ pub fn occupation_before(&self) -> usize {
+ return self.lf_act.lf_id;
+ }
+
+ pub fn occupation_after(&self) -> HashSet<usize> {
+ match self.act_kind {
+ ObservableActionKind::Emission(ref targets) => {
+ let mut occ : HashSet<usize> = HashSet::new();
+ for targ in targets {
+ occ.insert( targ.lf_id );
+ }
+ occ.insert( self.occupation_before() );
+ return occ;
+ },
+ _ => {
+ let mut occ : HashSet<usize> = HashSet::new();
+ occ.insert( self.occupation_before() );
+ return occ;
+ }
+ }
+ }
+
+}
+
diff --git a/src/core/syntax/data/builtin/bool.rs b/src/core/syntax/data/builtin/bool.rs
new file mode 100644
index 0000000..f8c5aa7
--- /dev/null
+++ b/src/core/syntax/data/builtin/bool.rs
@@ -0,0 +1,128 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::{HashSet,HashMap};
+
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::action::ValueOrNewFresh;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::var_ref::VariableReference;
+use crate::core::semantics::varmap::VarMapAble;
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum Bool_Compare {
+ Equal,
+ Greater,
+ GreaterOrEqual,
+ Lower,
+ LowerOrEqual,
+ Different
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum TD_Bool {
+ TRUE,
+ FALSE,
+ AND(Vec<TD_Bool>),
+ OR(Vec<TD_Bool>),
+ NOT(Box<TD_Bool>),
+ COMPARE(Bool_Compare, Box<TD_Generic>, Box<TD_Generic>),
+ Reference(VariableReference)
+}
+
+
+impl TD_Bool {
+
+ pub fn get_occuring_variables(&self) -> HashSet<usize> {
+ match self {
+ TD_Bool::TRUE => {
+ return HashSet::new();
+ },
+ TD_Bool::FALSE => {
+ return HashSet::new();
+ },
+ TD_Bool::AND(sub_bools) => {
+ let mut occs : HashSet<usize> = HashSet::new();
+ for sub_bool in sub_bools {
+ occs.extend(sub_bool.get_occuring_variables());
+ }
+ return occs;
+ },
+ TD_Bool::OR(sub_bools) => {
+ let mut occs : HashSet<usize> = HashSet::new();
+ for sub_bool in sub_bools {
+ occs.extend(sub_bool.get_occuring_variables());
+ }
+ return occs;
+ },
+ TD_Bool::NOT(sub_bool) => {
+ return (*sub_bool).get_occuring_variables();
+ },
+ TD_Bool::COMPARE(_,first,second) => {
+ let mut occs : HashSet<usize> = HashSet::new();
+ occs.extend(first.get_occuring_variables());
+ occs.extend(second.get_occuring_variables());
+ return occs;
+ },
+ TD_Bool::Reference(var_ref) => {
+ return var_ref.get_occuring_variables();
+ }
+ }
+ }
+}
+
+
+impl VarMapAble for TD_Bool {
+
+ fn apply_variable_mapping(&self, mapping : &HashMap<usize,usize>) -> TD_Bool {
+ match self {
+ TD_Bool::TRUE => {
+ return TD_Bool::TRUE;
+ },
+ TD_Bool::FALSE => {
+ return TD_Bool::FALSE;
+ },
+ TD_Bool::AND( sub_exprs ) => {
+ let mut updated_sub_exprs : Vec<TD_Bool> = Vec::new();
+ for expr in sub_exprs {
+ updated_sub_exprs.push( expr.apply_variable_mapping(mapping) );
+ }
+ return TD_Bool::AND(updated_sub_exprs);
+ },
+ TD_Bool::OR( sub_exprs ) => {
+ let mut updated_sub_exprs : Vec<TD_Bool> = Vec::new();
+ for expr in sub_exprs {
+ updated_sub_exprs.push( expr.apply_variable_mapping(mapping) );
+ }
+ return TD_Bool::OR(updated_sub_exprs);
+ },
+ TD_Bool::NOT( sub_expr ) => {
+ return TD_Bool::NOT( Box::new(sub_expr.apply_variable_mapping(mapping)) );
+ },
+ TD_Bool::COMPARE(kind, expr1, expr2) => {
+ let up_expr1 = expr1.apply_variable_mapping(mapping);
+ let up_expr2 = expr2.apply_variable_mapping(mapping);
+ return TD_Bool::COMPARE(kind.clone(),
+ Box::new(up_expr1),
+ Box::new(up_expr2));
+ },
+ TD_Bool::Reference( var_ref ) => {
+ return TD_Bool::Reference( var_ref.apply_variable_mapping(mapping) );
+ }
+ }
+ }
+
+}
+
diff --git a/src/core/syntax/data/builtin/float.rs b/src/core/syntax/data/builtin/float.rs
new file mode 100644
index 0000000..51538d4
--- /dev/null
+++ b/src/core/syntax/data/builtin/float.rs
@@ -0,0 +1,100 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::{HashMap,HashSet};
+use std::collections::btree_map::BTreeMap;
+
+use crate::core::context::execution::ExecutionContext;
+use crate::core::error::HibouCoreError;
+use crate::core::syntax::action::ValueOrNewFresh;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::var_ref::VariableReference;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::semantics::varmap::VarMapAble;
+use crate::core::syntax::data::builtin::number::*;
+
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum TD_Float {
+ Value(f64),
+ Minus(Box<TD_Float>),
+ Factor(Vec<(ARITH_FACTOR_SIGN,TD_Float)>),
+ Add(Vec<(ARITH_ADD_SIGN,TD_Float)>),
+ Reference(VariableReference)
+}
+
+impl TD_Float {
+
+ pub fn get_occuring_variables(&self) -> HashSet<usize> {
+ match self {
+ TD_Float::Value(_) => {
+ return HashSet::new();
+ },
+ TD_Float::Minus(sub_float) => {
+ return (*sub_float).get_occuring_variables();
+ },
+ TD_Float::Factor(sub_floats) => {
+ let mut occs : HashSet<usize> = HashSet::new();
+ for (_,sub_float) in sub_floats {
+ occs.extend(sub_float.get_occuring_variables());
+ }
+ return occs;
+ },
+ TD_Float::Add(sub_floats) => {
+ let mut occs : HashSet<usize> = HashSet::new();
+ for (_,sub_float) in sub_floats {
+ occs.extend(sub_float.get_occuring_variables());
+ }
+ return occs;
+ },
+ TD_Float::Reference(var_ref) => {
+ return var_ref.get_occuring_variables();
+ }
+ }
+ }
+}
+
+impl VarMapAble for TD_Float {
+
+ fn apply_variable_mapping(&self, mapping : &HashMap<usize,usize>) -> TD_Float {
+ match self {
+ TD_Float::Value( val ) => {
+ return TD_Float::Value( *val );
+ },
+ TD_Float::Minus( boxed_inv ) => {
+ let mapped = boxed_inv.apply_variable_mapping(mapping);
+ return TD_Float::Minus( Box::new(mapped) );
+ },
+ TD_Float::Factor( factors ) => {
+ let mut mapped_factors : Vec<(ARITH_FACTOR_SIGN,TD_Float)> = Vec::new();
+ for (sign,number) in factors {
+ mapped_factors.push( (sign.clone(), number.apply_variable_mapping(mapping)) );
+ }
+ return TD_Float::Factor( mapped_factors );
+ },
+ TD_Float::Add( adds ) => {
+ let mut mapped_adds : Vec<(ARITH_ADD_SIGN,TD_Float)> = Vec::new();
+ for (sign,number) in adds {
+ mapped_adds.push( (sign.clone(), number.apply_variable_mapping(mapping)) );
+ }
+ return TD_Float::Add( mapped_adds );
+ },
+ TD_Float::Reference( var_ref ) => {
+ return TD_Float::Reference( var_ref.apply_variable_mapping(mapping) );
+ }
+ }
+ }
+}
+
+
diff --git a/src/core/syntax/data/builtin/integer.rs b/src/core/syntax/data/builtin/integer.rs
new file mode 100644
index 0000000..6428059
--- /dev/null
+++ b/src/core/syntax/data/builtin/integer.rs
@@ -0,0 +1,99 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::{HashMap,HashSet};
+use std::collections::btree_map::BTreeMap;
+
+use crate::core::context::execution::ExecutionContext;
+use crate::core::error::HibouCoreError;
+use crate::core::syntax::action::ValueOrNewFresh;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::var_ref::VariableReference;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::semantics::varmap::VarMapAble;
+use crate::core::syntax::data::builtin::number::*;
+
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum TD_Integer {
+ Value(i64),
+ Minus(Box<TD_Integer>),
+ Factor(Vec<(ARITH_FACTOR_SIGN,TD_Integer)>),
+ Add(Vec<(ARITH_ADD_SIGN,TD_Integer)>),
+ Reference(VariableReference)
+}
+
+impl TD_Integer {
+
+ pub fn get_occuring_variables(&self) -> HashSet<usize> {
+ match self {
+ TD_Integer::Value(_) => {
+ return HashSet::new();
+ },
+ TD_Integer::Minus(sub_int) => {
+ return (*sub_int).get_occuring_variables();
+ },
+ TD_Integer::Factor(sub_ints) => {
+ let mut occs : HashSet<usize> = HashSet::new();
+ for (_,sub_int) in sub_ints {
+ occs.extend(sub_int.get_occuring_variables());
+ }
+ return occs;
+ },
+ TD_Integer::Add(sub_ints) => {
+ let mut occs : HashSet<usize> = HashSet::new();
+ for (_,sub_int) in sub_ints {
+ occs.extend(sub_int.get_occuring_variables());
+ }
+ return occs;
+ },
+ TD_Integer::Reference(var_ref) => {
+ return var_ref.get_occuring_variables();
+ }
+ }
+ }
+}
+
+impl VarMapAble for TD_Integer {
+
+ fn apply_variable_mapping(&self, mapping : &HashMap<usize,usize>) -> TD_Integer {
+ match self {
+ TD_Integer::Value( val ) => {
+ return TD_Integer::Value( *val );
+ },
+ TD_Integer::Minus( boxed_inv ) => {
+ let mapped = boxed_inv.apply_variable_mapping(mapping);
+ return TD_Integer::Minus( Box::new(mapped) );
+ },
+ TD_Integer::Factor( factors ) => {
+ let mut mapped_factors : Vec<(ARITH_FACTOR_SIGN,TD_Integer)> = Vec::new();
+ for (sign,number) in factors {
+ mapped_factors.push( (sign.clone(), number.apply_variable_mapping(mapping)) );
+ }
+ return TD_Integer::Factor( mapped_factors );
+ },
+ TD_Integer::Add( adds ) => {
+ let mut mapped_adds : Vec<(ARITH_ADD_SIGN,TD_Integer)> = Vec::new();
+ for (sign,number) in adds {
+ mapped_adds.push( (sign.clone(), number.apply_variable_mapping(mapping)) );
+ }
+ return TD_Integer::Add( mapped_adds );
+ },
+ TD_Integer::Reference( var_ref ) => {
+ return TD_Integer::Reference( var_ref.apply_variable_mapping(mapping) );
+ }
+ }
+ }
+}
+
diff --git a/src/core/syntax/data/builtin/mod.rs b/src/core/syntax/data/builtin/mod.rs
new file mode 100644
index 0000000..ead90c5
--- /dev/null
+++ b/src/core/syntax/data/builtin/mod.rs
@@ -0,0 +1,19 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod bool;
+pub mod number;
+pub mod integer;
+pub mod float;
+pub mod string;
diff --git a/src/core/syntax/data/builtin/number.rs b/src/core/syntax/data/builtin/number.rs
new file mode 100644
index 0000000..0e1021c
--- /dev/null
+++ b/src/core/syntax/data/builtin/number.rs
@@ -0,0 +1,26 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum ARITH_ADD_SIGN {
+ Plus,
+ Minus
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum ARITH_FACTOR_SIGN {
+ Mult,
+ Div
+}
+
diff --git a/src/core/syntax/data/builtin/string.rs b/src/core/syntax/data/builtin/string.rs
new file mode 100644
index 0000000..e1dfe6e
--- /dev/null
+++ b/src/core/syntax/data/builtin/string.rs
@@ -0,0 +1,69 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::{HashSet,HashMap};
+use std::collections::btree_map::BTreeMap;
+
+use crate::core::context::execution::ExecutionContext;
+use crate::core::error::HibouCoreError;
+use crate::core::syntax::action::ValueOrNewFresh;
+use crate::core::syntax::data::var_ref::VariableReference;
+use crate::core::semantics::varmap::VarMapAble;
+use crate::core::syntax::data::generic::TD_Generic;
+
+#[derive(Clone, PartialEq, Eq, Hash,Debug)]
+pub enum TD_String {
+ Value(String),
+ //Concat(Vec<TD_String>),
+ Reference(VariableReference)
+}
+
+impl TD_String {
+
+ pub fn get_occuring_variables(&self) -> HashSet<usize> {
+ match self {
+ TD_String::Value(_) => {
+ return HashSet::new();
+ },
+ TD_String::Reference(var_ref) => {
+ return var_ref.get_occuring_variables();
+ }
+ }
+ }
+
+}
+
+impl VarMapAble for TD_String {
+
+ fn apply_variable_mapping(&self, mapping : &HashMap<usize,usize>) -> TD_String {
+ match self {
+ TD_String::Value( val ) => {
+ return TD_String::Value( val.clone() );
+ },/*
+ TD_String::Concat( primary, adds ) => {
+ let up_primary = primary.apply_mapping(mapping);
+ let mut up_adds = Vec::new();
+ for add_str in adds {
+ up_adds.push( add_str.apply_mapping(mapping) );
+ }
+ return TD_String::Concat( Box::new(up_primary), up_adds );
+ },*/
+ TD_String::Reference( var_ref ) => {
+ return TD_String::Reference( var_ref.apply_variable_mapping(mapping) );
+ }
+ }
+ }
+
+}
+
diff --git a/src/core/syntax/data/generic.rs b/src/core/syntax/data/generic.rs
new file mode 100644
index 0000000..405799f
--- /dev/null
+++ b/src/core/syntax/data/generic.rs
@@ -0,0 +1,143 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::{HashSet,HashMap};
+use std::collections::btree_map::BTreeMap;
+
+use crate::core::context::execution::ExecutionContext;
+use crate::core::error::HibouCoreError;
+use crate::core::syntax::action::ValueOrNewFresh;
+use crate::core::context::general::GeneralContext;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::var_ref::VariableReference;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::float::TD_Float;
+use crate::core::syntax::data::builtin::string::TD_String;
+use crate::core::semantics::varmap::VarMapAble;
+
+#[derive(Clone, PartialEq, Debug)] // Eq, Hash,
+pub enum TD_Generic {
+ //Reference(VariableReference),
+ Bool(TD_Bool),
+ String(TD_String),
+ Integer(TD_Integer),
+ Float(TD_Float)
+}
+
+impl TD_Generic {
+
+ pub fn get_td_type(&self) -> TD_DataType {
+ match self {
+ TD_Generic::Bool(_) => {
+ return TD_DataType::Bool;
+ },
+ TD_Generic::String(_) => {
+ return TD_DataType::String;
+ },
+ TD_Generic::Integer(_) => {
+ return TD_DataType::Integer;
+ },
+ TD_Generic::Float(_) => {
+ return TD_DataType::Float;
+ }
+ }
+ }
+
+ pub fn get_occuring_variables(&self) -> HashSet<usize> {
+ match self {
+ TD_Generic::Bool(td_bool) => {
+ return td_bool.get_occuring_variables();
+ },
+ TD_Generic::String(td_string) => {
+ return td_string.get_occuring_variables();
+ },
+ TD_Generic::Integer(td_int) => {
+ return td_int.get_occuring_variables();
+ },
+ TD_Generic::Float(td_float) => {
+ return td_float.get_occuring_variables();
+ }
+ }
+ }
+
+ pub fn as_td_bool(&self) -> TD_Bool {
+ match self {
+ TD_Generic::Bool(td_bool) => {
+ return td_bool.clone();
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+
+ pub fn as_td_string(&self) -> TD_String {
+ match self {
+ TD_Generic::String(td_string) => {
+ return td_string.clone();
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+
+ pub fn as_td_int(&self) -> TD_Integer {
+ match self {
+ TD_Generic::Integer(td_int) => {
+ return td_int.clone();
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+
+ pub fn as_td_float(&self) -> TD_Float {
+ match self {
+ TD_Generic::Float(td_float) => {
+ return td_float.clone();
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+
+}
+
+impl VarMapAble for TD_Generic {
+
+ fn apply_variable_mapping(&self, mapping : &HashMap<usize,usize>) -> TD_Generic {
+ match self {/*
+ TD_Generic::Reference( var_ref ) => {
+ return TD_Generic::Reference( var_ref.apply_variable_mapping(mapping) );
+ },*/
+ TD_Generic::Bool( td_bool ) => {
+ return TD_Generic::Bool( td_bool.apply_variable_mapping(mapping) );
+ },
+ TD_Generic::Integer( td_num ) => {
+ return TD_Generic::Integer( td_num.apply_variable_mapping(mapping) );
+ },
+ TD_Generic::Float( td_num ) => {
+ return TD_Generic::Float( td_num.apply_variable_mapping(mapping) );
+ },
+ TD_Generic::String( td_string ) => {
+ return TD_Generic::String( td_string.apply_variable_mapping(mapping) );
+ }
+ }
+ }
+}
+
diff --git a/src/core/syntax/data/mod.rs b/src/core/syntax/data/mod.rs
new file mode 100644
index 0000000..4869aab
--- /dev/null
+++ b/src/core/syntax/data/mod.rs
@@ -0,0 +1,20 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod td_type;
+pub mod builtin;
+pub mod var_ref;
+pub mod generic;
+
+
diff --git a/src/core/syntax/data/td_type.rs b/src/core/syntax/data/td_type.rs
new file mode 100644
index 0000000..a6f8497
--- /dev/null
+++ b/src/core/syntax/data/td_type.rs
@@ -0,0 +1,85 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use crate::diversity;
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub enum TD_DataType {
+ //Clock,
+ Bool,
+ String,
+ Integer,
+ Float
+}
+
+impl TD_DataType {
+
+ pub fn from_grpc(grpc_data_type_id : i32) -> TD_DataType {
+ if grpc_data_type_id == (diversity::DataType::Boolean as i32) {
+ return TD_DataType::Bool;
+ } else if grpc_data_type_id == (diversity::DataType::String as i32) {
+ return TD_DataType::String;
+ } else if grpc_data_type_id == (diversity::DataType::Integer as i32) {
+ return TD_DataType::Integer;
+ } else if grpc_data_type_id == (diversity::DataType::Float as i32) {
+ return TD_DataType::Float;
+ } else if grpc_data_type_id == (diversity::DataType::Rational as i32) {
+ return TD_DataType::Float;
+ } else {
+ println!("{}", grpc_data_type_id);
+ panic!();
+ }
+ }
+
+ pub fn as_xlia_str(&self) -> String {
+ match self {/*
+ TD_DataType::Clock => {
+ return "Real".to_string();
+ },*/
+ TD_DataType::Bool => {
+ return "bool".to_string();
+ },
+ TD_DataType::String => {
+ return "string".to_string();
+ },
+ TD_DataType::Integer => {
+ return "int".to_string();
+ },
+ TD_DataType::Float => {
+ return "float".to_string();
+ },
+ }
+ }
+
+ pub fn as_smtlib_str(&self) -> String {
+ match self {/*
+ TD_DataType::Clock => {
+ return "Real".to_string();
+ },*/
+ TD_DataType::Bool => {
+ return "Bool".to_string();
+ },
+ TD_DataType::String => {
+ return "String".to_string();
+ },
+ TD_DataType::Integer => {
+ return "Int".to_string();
+ },
+ TD_DataType::Float => {
+ return "Real".to_string();
+ },
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/core/syntax/data/var_ref.rs b/src/core/syntax/data/var_ref.rs
new file mode 100644
index 0000000..d7f225c
--- /dev/null
+++ b/src/core/syntax/data/var_ref.rs
@@ -0,0 +1,78 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::{HashSet,HashMap};
+
+use std::collections::btree_map::BTreeMap;
+
+use crate::core::context::execution::ExecutionContext;
+use crate::core::error::HibouCoreError;
+use crate::core::syntax::action::ValueOrNewFresh;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::builtin::float::*;
+use crate::core::syntax::data::builtin::integer::*;
+use crate::core::syntax::data::builtin::string::*;
+use crate::core::syntax::data::builtin::bool::*;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::semantics::varmap::VarMapAble;
+
+#[derive(Clone, PartialEq, Eq, Hash,Debug)]
+pub enum VariableReference {
+ MSG_PARAMETER(usize,usize),
+ VARIABLE(usize),
+ SYMBOL(usize)
+}
+
+impl VariableReference {
+
+ pub fn get_occuring_variables(&self) -> HashSet<usize> {
+ match self {
+ VariableReference::VARIABLE(var_id) => {
+ let mut var_set : HashSet<usize> = HashSet::new();
+ var_set.insert( *var_id );
+ return var_set;
+ },
+ _ => {
+ return HashSet::new();
+ }
+ }
+ }
+
+}
+
+impl VarMapAble for VariableReference {
+
+ fn apply_variable_mapping(&self, mapping : &HashMap<usize,usize>) -> VariableReference {
+ match self {
+ VariableReference::VARIABLE( vr_id ) => {
+ match mapping.get(vr_id) {
+ None => {
+ return VariableReference::VARIABLE( *vr_id );
+ },
+ Some( up_vr_id ) => {
+ return VariableReference::VARIABLE( *up_vr_id );
+ }
+ }
+ },
+ VariableReference::SYMBOL( symb_id ) => {
+ return VariableReference::SYMBOL( *symb_id );
+ },
+ VariableReference::MSG_PARAMETER( ms_id, pr_id ) => {
+ return VariableReference::MSG_PARAMETER( *ms_id, *pr_id );
+ }
+ }
+ }
+
+}
+
diff --git a/src/core/syntax/interaction.rs b/src/core/syntax/interaction.rs
new file mode 100644
index 0000000..67d8f73
--- /dev/null
+++ b/src/core/syntax/interaction.rs
@@ -0,0 +1,376 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::cmp;
+
+use crate::core::syntax::position::*;
+use crate::core::syntax::action::*;
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum ScheduleOperatorKind {
+ Strict,
+ Seq,
+ Par
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum Interaction {
+ Empty,
+ Action(ObservableAction),
+ Strict(Box<Interaction>,Box<Interaction>),
+ Seq(Box<Interaction>,Box<Interaction>),
+ Alt(Box<Interaction>,Box<Interaction>),
+ Par(Box<Interaction>,Box<Interaction>),
+ Loop(ScheduleOperatorKind,Box<Interaction>),
+ Scope(Vec<usize>,Box<Interaction>)
+}
+
+
+impl Interaction {
+
+ pub fn substitute(&self, subst_int : Interaction, my_pos : &Position) -> Interaction {
+ match my_pos {
+ Position::Epsilon => {
+ return subst_int;
+ },
+ Position::Left(sub_pos) => {
+ match self {
+ Interaction::Strict(i1,i2) => {
+ let substituted_i1 = (*i1).substitute(subst_int, &(*sub_pos) );
+ if substituted_i1 == Interaction::Empty {
+ return *i2.clone();
+ } else {
+ return Interaction::Strict( Box::new(substituted_i1), (*i2).clone() );
+ }
+ },
+ Interaction::Seq(i1,i2) => {
+ let substituted_i1 = (*i1).substitute(subst_int, &(*sub_pos) );
+ if substituted_i1 == Interaction::Empty {
+ return *i2.clone();
+ } else {
+ return Interaction::Seq( Box::new(substituted_i1), (*i2).clone() );
+ }
+ },
+ Interaction::Alt(i1,i2) => {
+ return Interaction::Alt( Box::new((*i1).substitute(subst_int, &(*sub_pos) ) ), (*i2).clone() );
+ },
+ Interaction::Par(i1,i2) => {
+ let substituted_i1 = (*i1).substitute(subst_int, &(*sub_pos) );
+ if substituted_i1 == Interaction::Empty {
+ return *i2.clone();
+ } else {
+ return Interaction::Par( Box::new(substituted_i1), (*i2).clone() );
+ }
+ },
+ Interaction::Loop(kind,i1) => {
+ let substituted_i1 = (*i1).substitute(subst_int, &(*sub_pos) );
+ if substituted_i1 == Interaction::Empty {
+ return Interaction::Empty;
+ } else {
+ return Interaction::Loop(kind.clone(), Box::new(substituted_i1) );
+ }
+ },
+ Interaction::Scope(scope,i1) => {
+ let substituted_i1 = (*i1).substitute(subst_int, &(*sub_pos) );
+ if substituted_i1 == Interaction::Empty {
+ return Interaction::Empty;
+ } else {
+ return Interaction::Scope(scope.clone(), Box::new(substituted_i1) );
+ }
+ },
+ _ => {
+ panic!("cannot substitute on a position that does not exist within the interaction");
+ }
+ }
+ },
+ Position::Right(sub_pos) => {
+ match self {
+ Interaction::Strict(i1,i2) => {
+ let substituted_i2 = (*i2).substitute(subst_int, &(*sub_pos) );
+ if substituted_i2 == Interaction::Empty {
+ return *i1.clone();
+ } else {
+ return Interaction::Strict( (*i1).clone(), Box::new(substituted_i2) );
+ }
+ },
+ Interaction::Seq(i1,i2) => {
+ let substituted_i2 = (*i2).substitute(subst_int, &(*sub_pos) );
+ if substituted_i2 == Interaction::Empty {
+ return *i1.clone();
+ } else {
+ return Interaction::Seq( (*i1).clone(), Box::new(substituted_i2) );
+ }
+ },
+ Interaction::Alt(i1,i2) => {
+ return Interaction::Alt( (*i1).clone(), Box::new((*i2).substitute(subst_int, &(*sub_pos) )) );
+ },
+ Interaction::Par(i1,i2) => {
+ let substituted_i2 = (*i2).substitute(subst_int, &(*sub_pos) );
+ if substituted_i2 == Interaction::Empty {
+ return *i1.clone();
+ } else {
+ return Interaction::Par( (*i1).clone(), Box::new(substituted_i2) );
+ }
+ },
+ _ => {
+ panic!("cannot substitute on a position that does not exist within the interaction");
+ }
+ }
+ }
+ }
+ }
+
+ pub fn decorate_with_initial_positions(&self, prefix : Vec<u32>) -> Interaction {
+ match &self {
+ &Interaction::Empty => {
+ return Interaction::Empty;
+ }, &Interaction::Action(ref act ) => {
+ let mut new_act = act.clone();
+ new_act.original_position = Some(prefix);
+ return Interaction::Action( new_act )
+ }, &Interaction::Strict(ref i1, ref i2) => {
+ let mut left = prefix.clone();
+ left.push(1);
+ let new_i1 = i1.decorate_with_initial_positions(left);
+ let mut right = prefix.clone();
+ right.push(2);
+ let new_i2 = i2.decorate_with_initial_positions(right);
+ return Interaction::Strict(Box::new(new_i1),Box::new(new_i2));
+ }, &Interaction::Seq(ref i1, ref i2) => {
+ let mut left = prefix.clone();
+ left.push(1);
+ let new_i1 = i1.decorate_with_initial_positions(left);
+ let mut right = prefix.clone();
+ right.push(2);
+ let new_i2 = i2.decorate_with_initial_positions(right);
+ return Interaction::Seq(Box::new(new_i1),Box::new(new_i2));
+ }, &Interaction::Par(ref i1, ref i2) => {
+ let mut left = prefix.clone();
+ left.push(1);
+ let new_i1 = i1.decorate_with_initial_positions(left);
+ let mut right = prefix.clone();
+ right.push(2);
+ let new_i2 = i2.decorate_with_initial_positions(right);
+ return Interaction::Par(Box::new(new_i1),Box::new(new_i2));
+ }, &Interaction::Alt(ref i1, ref i2) => {
+ let mut left = prefix.clone();
+ left.push(1);
+ let new_i1 = i1.decorate_with_initial_positions(left);
+ let mut right = prefix.clone();
+ right.push(2);
+ let new_i2 = i2.decorate_with_initial_positions(right);
+ return Interaction::Alt(Box::new(new_i1),Box::new(new_i2));
+ }, &Interaction::Loop(ref lkind, ref i1) => {
+ let mut left = prefix.clone();
+ left.push(1);
+ let new_i1 = i1.decorate_with_initial_positions(left);
+ return Interaction::Loop(lkind.clone(),Box::new(new_i1));
+ }, &Interaction::Scope(ref scope, ref i1) => {
+ let mut left = prefix.clone();
+ left.push(1);
+ let new_i1 = i1.decorate_with_initial_positions(left);
+ return Interaction::Scope(scope.clone(),Box::new(new_i1));
+ }
+ }
+ }
+
+ pub fn as_leaf(&self) -> &ObservableAction {
+ match self {
+ Interaction::Action(act) => {
+ return act;
+ },
+ _ => {
+ panic!("called as_leaf on something that's not a leaf : {:?}", self);
+ }
+ }
+ }
+
+ pub fn get_sub_interaction(&self, my_pos : &Position) -> &Interaction {
+ match my_pos {
+ Position::Epsilon => {
+ return self;
+ },
+ Position::Left(sub_pos) => {
+ match self {
+ &Interaction::Seq(ref i1, ref i2) => {
+ return (&*i1).get_sub_interaction( &(*sub_pos) );
+ },
+ &Interaction::Strict(ref i1, ref i2) => {
+ return (&*i1).get_sub_interaction( &(*sub_pos) );
+ },
+ &Interaction::Alt(ref i1, ref i2) => {
+ return (&*i1).get_sub_interaction( &(*sub_pos) );
+ },
+ &Interaction::Par(ref i1, ref i2) => {
+ return (&*i1).get_sub_interaction( &(*sub_pos) );
+ },
+ &Interaction::Loop(_ , ref i1) => {
+ return (&*i1).get_sub_interaction( &(*sub_pos) );
+ },
+ &Interaction::Scope(_, ref i1) => {
+ return (&*i1).get_sub_interaction( &(*sub_pos) );
+ },
+ _ => {
+ panic!();
+ }
+ }
+ },
+ Position::Right(sub_pos) => {
+ match self {
+ &Interaction::Seq(ref i1, ref i2) => {
+ return (&*i2).get_sub_interaction( &(*sub_pos) );
+ },
+ &Interaction::Strict(ref i1, ref i2) => {
+ return (&*i2).get_sub_interaction( &(*sub_pos) );
+ },
+ &Interaction::Alt(ref i1, ref i2) => {
+ return (&*i2).get_sub_interaction( &(*sub_pos) );
+ },
+ &Interaction::Par(ref i1, ref i2) => {
+ return (&*i2).get_sub_interaction( &(*sub_pos) );
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+ }
+ }
+
+ pub fn express_empty(&self) -> bool {
+ match self {
+ &Interaction::Empty => {
+ return true;
+ }, &Interaction::Action(_) => {
+ return false;
+ }, &Interaction::Strict(ref i1, ref i2) => {
+ return i1.express_empty() && i2.express_empty();
+ }, &Interaction::Seq(ref i1, ref i2) => {
+ return i1.express_empty() && i2.express_empty();
+ }, &Interaction::Par(ref i1, ref i2) => {
+ return i1.express_empty() && i2.express_empty();
+ }, &Interaction::Alt(ref i1, ref i2) => {
+ return i1.express_empty() || i2.express_empty();
+ }, &Interaction::Loop(_, _) => {
+ return true;
+ }, &Interaction::Scope(_, ref i1) => {
+ return i1.express_empty();
+ }
+ }
+ }
+
+ pub fn loop_depth(&self) -> u32 {
+ match self {
+ &Interaction::Empty => {
+ return 0;
+ }, &Interaction::Action(_) => {
+ return 0;
+ }, &Interaction::Strict(ref i1, ref i2) => {
+ return cmp::max(i1.loop_depth(),i2.loop_depth());
+ }, &Interaction::Seq(ref i1, ref i2) => {
+ return cmp::max(i1.loop_depth(),i2.loop_depth());
+ }, &Interaction::Alt(ref i1, ref i2) => {
+ return cmp::max(i1.loop_depth(),i2.loop_depth());
+ }, &Interaction::Par(ref i1, ref i2) => {
+ return cmp::max(i1.loop_depth(),i2.loop_depth());
+ }, &Interaction::Loop(_, ref i1) => {
+ return 1 + i1.loop_depth();
+ }, &Interaction::Scope(_, ref i1) => {
+ return i1.loop_depth();
+ }
+ }
+ }
+
+ pub fn get_loop_depth_at_pos(&self, my_pos : &Position) -> u32 {
+ match my_pos {
+ Position::Epsilon => {
+ return 0;
+ },
+ Position::Left(sub_pos) => {
+ match self {
+ &Interaction::Alt(ref i1, ref i2) => {
+ return i1.get_loop_depth_at_pos(&(*sub_pos) );
+ },
+ &Interaction::Strict(ref i1, ref i2) => {
+ return i1.get_loop_depth_at_pos(&(*sub_pos) );
+ },
+ &Interaction::Seq(ref i1, ref i2) => {
+ return i1.get_loop_depth_at_pos(&(*sub_pos) );
+ },
+ &Interaction::Par(ref i1, ref i2) => {
+ return i1.get_loop_depth_at_pos(&(*sub_pos) );
+ },
+ &Interaction::Loop(_, ref i1) => {
+ return 1 + i1.get_loop_depth_at_pos(&(*sub_pos) );
+ },
+ &Interaction::Scope(_, ref i1) => {
+ return i1.get_loop_depth_at_pos(&(*sub_pos) );
+ },
+ _ => {
+ panic!("undefined pos");
+ }
+ }
+ },
+ Position::Right(sub_pos) => {
+ match self {
+ &Interaction::Alt(ref i1, ref i2) => {
+ return i2.get_loop_depth_at_pos(&(*sub_pos) );
+ },
+ &Interaction::Strict(ref i1, ref i2) => {
+ return i2.get_loop_depth_at_pos(&(*sub_pos) );
+ },
+ &Interaction::Seq(ref i1, ref i2) => {
+ return i2.get_loop_depth_at_pos(&(*sub_pos) );
+ },
+ &Interaction::Par(ref i1, ref i2) => {
+ return i2.get_loop_depth_at_pos(&(*sub_pos) );
+ },
+ _ => {
+ panic!("undefined pos");
+ }
+ }
+ }
+ }
+ }
+
+ pub fn avoids(&self, lf_id : usize) -> bool {
+ match self {
+ &Interaction::Empty => {
+ return true;
+ }, &Interaction::Action(ref act) => {
+ if act.occupation_after().contains(&lf_id) {
+ return false;
+ } else {
+ return true;
+ }
+ }, &Interaction::Strict(ref i1, ref i2) => {
+ return i1.avoids(lf_id) && i2.avoids(lf_id);
+ }, &Interaction::Seq(ref i1, ref i2) => {
+ return i1.avoids(lf_id) && i2.avoids(lf_id);
+ }, &Interaction::Par(ref i1, ref i2) => {
+ return i1.avoids(lf_id) && i2.avoids(lf_id);
+ }, &Interaction::Alt(ref i1, ref i2) => {
+ return i1.avoids(lf_id) || i2.avoids(lf_id);
+ }, &Interaction::Loop(_, _) => {
+ return true;
+ }, &Interaction::Scope(_, ref i1) => {
+ return i1.avoids(lf_id);
+ }
+ }
+ }
+
+}
+
+
+
diff --git a/src/core/syntax/mod.rs b/src/core/syntax/mod.rs
new file mode 100644
index 0000000..e1a7d57
--- /dev/null
+++ b/src/core/syntax/mod.rs
@@ -0,0 +1,22 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod position;
+pub mod action;
+
+pub mod interaction;
+pub mod data;
+
+
+
diff --git a/src/core/syntax/position.rs b/src/core/syntax/position.rs
new file mode 100644
index 0000000..c9d322b
--- /dev/null
+++ b/src/core/syntax/position.rs
@@ -0,0 +1,126 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub static SYNTAX_POSITION_LEFT: &'static str = "1";
+pub static SYNTAX_POSITION_RIGHT: &'static str = "2";
+pub static SYNTAX_POSITION_EPSILON: &'static str = "ε";
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub enum Position {
+ Left(Box<Position>),
+ Right(Box<Position>),
+ Epsilon
+}
+
+
+impl Position {
+
+ pub fn from_vec(pos_vec : &mut Vec<u32>) -> Position {
+ if pos_vec.len() == 0 {
+ return Position::Epsilon;
+ } else {
+ let first = pos_vec.remove(0);
+ let continuation = Position::from_vec(pos_vec);
+ if first == 1 {
+ return Position::Left( Box::new(continuation) );
+ } else if first == 2 {
+ return Position::Right( Box::new(continuation) );
+ } else {
+ panic!();
+ }
+ }
+ }
+
+}
+
+use core::cmp::Ordering;
+
+impl PartialOrd for Position {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for Position {
+ fn cmp(&self, other: &Self) -> Ordering {
+ match self {
+ &Position::Epsilon => {
+ match other {
+ &Position::Epsilon => {
+ return Ordering::Equal;
+ },
+ _ => {
+ return Ordering::Less;
+ }
+ }
+ },
+ &Position::Left(ref in_self) => {
+ match other {
+ &Position::Left(ref in_other) => {
+ return (**in_self).cmp( &**in_other );
+ },
+ &Position::Right(ref in_other) => {
+ return Ordering::Less;
+ },
+ &Position::Epsilon => {
+ return Ordering::Greater;
+ }
+ }
+ },
+ &Position::Right(ref in_self) => {
+ match other {
+ &Position::Left(ref in_other) => {
+ return Ordering::Greater;
+ },
+ &Position::Right(ref in_other) => {
+ return (**in_self).cmp( &**in_other );
+ },
+ &Position::Epsilon => {
+ return Ordering::Greater;
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+impl Position {
+
+ pub fn as_text(&self) -> String {
+ match self {
+ Position::Left(ref in_self) => {
+ let mut my_string = SYNTAX_POSITION_LEFT.to_string();
+ my_string.push_str( &(*in_self).as_text() );
+ return my_string;
+ },
+ Position::Right(ref in_self) => {
+ let mut my_string = SYNTAX_POSITION_RIGHT.to_string();
+ my_string.push_str( &(*in_self).as_text() );
+ return my_string;
+ },
+ Position::Epsilon => {
+ return SYNTAX_POSITION_EPSILON.to_string();
+ }
+ }
+ }
+
+}
+
+
+
+
+
+
+*/
diff --git a/src/core/trace.rs b/src/core/trace.rs
new file mode 100644
index 0000000..e9a73b1
--- /dev/null
+++ b/src/core/trace.rs
@@ -0,0 +1,93 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashSet;
+
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::builtin::float::TD_Float;
+
+use crate::core::syntax::action::ObservableAction;
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum TraceActionKind {
+ Reception,
+ Emission
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub struct TraceAction {
+ pub delay : Option<TD_Float>,
+ pub lf_id : usize,
+ pub act_kind : TraceActionKind,
+ pub ms_id : usize,
+ pub arguments : Vec<TD_Generic>
+}
+
+impl TraceAction {
+
+ pub fn is_signature_match(&self, model_action: &ObservableAction) -> bool {
+ if model_action.lf_act.lf_id != self.lf_id {
+ return false;
+ }
+ if model_action.ms_id != self.ms_id {
+ return false;
+ }
+ if self.act_kind != model_action.get_action_kind() {
+ return false;
+ }
+ if self.arguments.len() != model_action.params.len() {
+ return false;
+ }
+ return true;
+ }
+}
+
+
+#[derive(Clone, PartialEq, Debug)]
+pub struct MultiTraceCanal {
+ pub lifelines : HashSet<usize>,
+ pub trace : Vec<TraceAction>
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub struct AnalysableMultiTrace {
+ pub canals : Vec<MultiTraceCanal>
+}
+
+impl AnalysableMultiTrace {
+ pub fn new(canals:Vec<MultiTraceCanal>) -> AnalysableMultiTrace {
+ return AnalysableMultiTrace{canals};
+ }
+
+ pub fn length(&self) -> usize {
+ let mut length = 0;
+ for canal in &self.canals {
+ length = length + (canal.trace.len());
+ }
+ return length;
+ }
+
+ pub fn is_any_component_empty(&self) -> bool {
+ for canal in &self.canals {
+ if canal.trace.len() == 0 {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
+
+
+
diff --git a/src/diversity.rs b/src/diversity.rs
new file mode 100644
index 0000000..311592a
--- /dev/null
+++ b/src/diversity.rs
@@ -0,0 +1,16 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+tonic::include_proto!("sep.grpc");
+
diff --git a/src/from_text/action/action.rs b/src/from_text/action/action.rs
new file mode 100644
index 0000000..7c03eab
--- /dev/null
+++ b/src/from_text/action/action.rs
@@ -0,0 +1,226 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use pest::iterators::{Pair,Pairs};
+
+
+
+use crate::core::syntax::action::*;
+use crate::core::context::general::GeneralContext;
+
+use crate::from_text::parser::*;
+use crate::from_text::error::HibouParsingError;
+
+use crate::from_text::data::generic::parse_data;
+use crate::from_text::action::lf_act::parse_lifeline_action;
+
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::td_type::TD_DataType;
+
+fn parse_message_parameters(gen_ctx : &GeneralContext,
+ msg_param_pair : Pair<Rule>,
+ ms_name : &String,
+ ms_specs : Vec<(TD_DataType,Option<String>)>) -> Result<Vec<ValueOrNewFresh>,HibouParsingError> {
+ let mut params : Vec<ValueOrNewFresh> = Vec::new();
+ let mut current_id : usize = 0;
+ for value_or_new_fresh_pair in msg_param_pair.into_inner() {
+ match value_or_new_fresh_pair.as_rule() {
+ Rule::TD_VALUE => {
+ match parse_data(gen_ctx,value_or_new_fresh_pair,&None) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( carried_data ) => {
+ match ms_specs.get(current_id) {
+ None => {
+ return Err( HibouParsingError::UnknownMessageParameter( ms_name.clone(), current_id ) );
+ },
+ Some( (expected_type,_) ) => {
+ let got_type = carried_data.get_td_type();
+ if &got_type != expected_type {
+ return Err( HibouParsingError::WrongMessageParameterType(expected_type.clone(),
+ got_type,
+ ms_name.clone(),
+ format!("{:?}", ms_specs) ) );
+ }
+ params.push( ValueOrNewFresh::Value(carried_data) );
+ }
+ }
+ }
+ }
+ },
+ Rule::NEW_FRESH => {
+ params.push( ValueOrNewFresh::NewFresh );
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", value_or_new_fresh_pair.as_rule() );
+ }
+ }
+ current_id = current_id + 1;
+ }
+ let arg_count = params.len();
+ if arg_count != ms_specs.len() {
+ return Err( HibouParsingError::WrongMessageParametersNumber(ms_specs.len(), arg_count,ms_name.clone()) );
+ }
+ return Ok( params );
+}
+
+pub fn parse_reception(gen_ctx : &GeneralContext, contents : &mut Pairs<Rule>) -> Result<ObservableAction,HibouParsingError> {
+ let message_name_pair = contents.next().unwrap();
+ let message_name : String = message_name_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_ms_id( &message_name ) {
+ None => {
+ return Err( HibouParsingError::MissingMessageDeclarationError(message_name) );
+ },
+ Some( ms_id ) => {
+ let ms_specs = gen_ctx.get_ms_spec(ms_id).unwrap();
+ // ***
+ let params : Vec<ValueOrNewFresh>;
+ let lf_act : LifelineAction;
+ let next_pair = contents.next().unwrap();
+ let lf_pair : Pair<Rule>;
+ match next_pair.as_rule() {
+ Rule::SD_MESSAGE_PARAMETERS => {
+ match parse_message_parameters(gen_ctx, next_pair, &message_name, ms_specs) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( msg_parameters ) => {
+ params = msg_parameters;
+ }
+ }
+ lf_pair = contents.next().unwrap();
+ },
+ Rule::SD_LIFELINE_ACTION => {
+ params = Vec::new();
+ lf_pair = next_pair;
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+ // ***
+ match parse_lifeline_action(gen_ctx, lf_pair, &Some(ms_id)) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( lf_act ) => {
+ let reception_act = ObservableAction{
+ lf_act:lf_act,
+ act_kind:ObservableActionKind::Reception,
+ ms_id:ms_id,
+ params:params,
+ original_position:None};
+ return Ok( reception_act );
+ }
+ }
+ }
+ }
+}
+
+pub fn parse_emission(gen_ctx : &GeneralContext, contents : &mut Pairs<Rule>) -> Result<ObservableAction,HibouParsingError> {
+ // ***
+ match parse_lifeline_action(gen_ctx, contents.next().unwrap(),&None) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( lf_act ) => {
+ let message_name : String = contents.next().unwrap().as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_ms_id( &message_name ) {
+ None => {
+ return Err( HibouParsingError::MissingMessageDeclarationError( message_name ) );
+ },
+ Some( ms_id ) => {
+ let mut targets : Vec<LifelineAction>;
+ let params : Vec<ValueOrNewFresh>;
+ match contents.next() {
+ None => {
+ targets = Vec::new();
+ params = Vec::new();
+ },
+ Some( next_pair ) => {
+ let target_pair_opt : Option<Pair<Rule>>;
+ match next_pair.as_rule() {
+ Rule::SD_MESSAGE_PARAMETERS => {
+ let ms_specs = gen_ctx.get_ms_spec(ms_id).unwrap();
+ match parse_message_parameters(gen_ctx, next_pair, &message_name, ms_specs) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( msg_parameters ) => {
+ params = msg_parameters;
+ }
+ }
+ target_pair_opt = contents.next();
+ },
+ Rule::SD_EMISSION_TARGET => {
+ params = Vec::new();
+ target_pair_opt = Some(next_pair);
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+ // ***
+ match target_pair_opt {
+ None => {
+ targets = Vec::new();
+ },
+ Some( target_pair ) => {
+ targets = Vec::new();
+ let inner_target_pair = target_pair.into_inner().next().unwrap();
+ match inner_target_pair.as_rule() {
+ Rule::SD_LIFELINE_ACTION => {
+ match parse_lifeline_action(gen_ctx,inner_target_pair,&Some(ms_id)) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok(target_lf_act) => {
+ targets.push( target_lf_act );
+ }
+ }
+ },
+ Rule::SD_EMISSION_TARGETS => {
+ for targ_name in inner_target_pair.into_inner() {
+ match parse_lifeline_action(gen_ctx,targ_name, &Some(ms_id)) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok(target_lf_act) => {
+ targets.push( target_lf_act );
+ }
+ }
+ }
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+ }
+ }
+ }
+ let emission_act = ObservableAction{
+ lf_act:lf_act,
+ act_kind:ObservableActionKind::Emission(targets),
+ ms_id:ms_id,
+ params:params,
+ original_position:None};
+ return Ok( emission_act );
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/from_text/action/amble.rs b/src/from_text/action/amble.rs
new file mode 100644
index 0000000..924307b
--- /dev/null
+++ b/src/from_text/action/amble.rs
@@ -0,0 +1,132 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use pest::iterators::{Pair,Pairs};
+
+
+
+use crate::core::syntax::action::{ValueOrNewFresh,LifelineAction,ActionAmbleItem};
+use crate::core::context::general::GeneralContext;
+
+use crate::from_text::parser::*;
+use crate::from_text::error::HibouParsingError;
+use crate::from_text::data::generic::parse_data;
+use crate::from_text::data::logic::parse_logic_expr;
+
+pub fn parse_amble(gen_ctx : &GeneralContext, amble_pair : Pair<Rule>, opt_ms_id : &Option<usize>) -> Result<Vec<ActionAmbleItem>,HibouParsingError> {
+ let mut amble : Vec<ActionAmbleItem> = Vec::new();
+ for item_pair in amble_pair.into_inner() {
+ match item_pair.as_rule() {
+ Rule::SD_OPERATION => {
+ match parse_operations(gen_ctx,item_pair, opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut operations_amble ) => {
+ amble.append( &mut operations_amble );
+ }
+ }
+ },
+ Rule::SD_GUARD => {
+ match parse_guards(gen_ctx, item_pair, opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut guards_amble ) => {
+ amble.append( &mut guards_amble );
+ }
+ }
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+ return Ok( amble );
+}
+
+
+fn parse_guards(gen_ctx : &GeneralContext, guard_pairs : Pair<Rule>, opt_ms_id : &Option<usize>) -> Result<Vec<ActionAmbleItem>,HibouParsingError> {
+ let mut guards : Vec<ActionAmbleItem> = Vec::new();
+ for guard_pair in guard_pairs.into_inner() {
+ match parse_logic_expr(gen_ctx,guard_pair, opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( td_bool ) => {
+ guards.push( ActionAmbleItem::Guard(td_bool) );
+ }
+ }
+ }
+ return Ok( guards );
+}
+
+fn parse_operations(gen_ctx : &GeneralContext, operations_pairs : Pair<Rule>, opt_ms_id : &Option<usize>) -> Result<Vec<ActionAmbleItem>,HibouParsingError> {
+ let mut operations : Vec<ActionAmbleItem> = Vec::new();
+ for operation_pair in operations_pairs.into_inner() {
+ match operation_pair.as_rule() {
+ Rule::OPERATION_RESET => {
+ let var_to_reset_pair = operation_pair.into_inner().next().unwrap();
+ let var_to_reset_name : String = var_to_reset_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_vr_id(&var_to_reset_name ) {
+ None => {
+ return Err( HibouParsingError::MissingVariableDeclarationError( var_to_reset_name ) );
+ },
+ Some( vr_id ) => {
+ if gen_ctx.is_clock( vr_id ) {
+ operations.push( ActionAmbleItem::Reset(vr_id) );
+ } else {
+ return Err( HibouParsingError::ClockMisuse( format!("can only reset clocks ; tried to reset '{:}' of index '{}' which is not a clock - clocks are {:?}", var_to_reset_name,vr_id,gen_ctx.get_clocks() ) ) );
+ }
+ }
+ }
+ },
+ Rule::OPERATION_ASSIGNMENT => {
+ let mut op_content = operation_pair.into_inner();
+ let vr_name : String = op_content.next().unwrap().as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let value_or_newfresh_pair = op_content.next().unwrap();
+ match gen_ctx.get_vr_id(&vr_name) {
+ None => {
+ return Err( HibouParsingError::MissingVariableDeclarationError( vr_name ) );
+ },
+ Some( vr_id ) => {
+ match value_or_newfresh_pair.as_rule() {
+ Rule::TD_VALUE => {
+ match parse_data(gen_ctx,value_or_newfresh_pair, opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( td_generic )=> {
+ operations.push( ActionAmbleItem::Assignment(vr_id, ValueOrNewFresh::Value(td_generic) ) );
+ }
+ }
+ },
+ Rule::NEW_FRESH => {
+ operations.push( ActionAmbleItem::Assignment(vr_id, ValueOrNewFresh::NewFresh ) );
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+ }
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+ return Ok( operations );
+}
+
diff --git a/src/from_text/action/lf_act.rs b/src/from_text/action/lf_act.rs
new file mode 100644
index 0000000..fd9035d
--- /dev/null
+++ b/src/from_text/action/lf_act.rs
@@ -0,0 +1,97 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use pest::iterators::{Pair,Pairs};
+
+
+
+use crate::core::syntax::action::*;
+use crate::core::context::general::GeneralContext;
+
+use crate::from_text::error::HibouParsingError;
+
+use crate::from_text::parser::*;
+use crate::from_text::action::amble::parse_amble;
+use crate::from_text::data::generic::parse_data;
+
+
+pub fn parse_lifeline_action(gen_ctx : &GeneralContext,
+ lifeline_action : Pair<Rule>,
+ opt_ms_id : &Option<usize>) -> Result<LifelineAction,HibouParsingError> {
+
+ let preamble : Vec<ActionAmbleItem>;
+ let postamble : Vec<ActionAmbleItem>;
+ let lf_id : usize;
+ // ***
+ let mut lifeline_action_pairs = lifeline_action.into_inner();
+ // ***
+ let first_arg = lifeline_action_pairs.next().unwrap();
+ match first_arg.as_rule() {
+ Rule::SD_ACTION_AMBLE => {
+ match parse_amble(gen_ctx, first_arg, &None) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( amble ) => {
+ preamble = amble;
+ let lf_name : String = lifeline_action_pairs.next().unwrap().as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_lf_id( &lf_name) {
+ None => {
+ return Err(HibouParsingError::MissingLifelineDeclarationError(lf_name));
+ },
+ Some( got_lf_id ) => {
+ lf_id = got_lf_id;
+ }
+ }
+ }
+ }
+ },
+ Rule::LIFELINE_LABEL => {
+ preamble = Vec::new();
+ let lf_name : String = first_arg.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_lf_id( &lf_name) {
+ None => {
+ return Err(HibouParsingError::MissingLifelineDeclarationError(lf_name));
+ },
+ Some( got_lf_id ) => {
+ lf_id = got_lf_id;
+ }
+ }
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", first_arg.as_rule() );
+ }
+ }
+ // ***
+ match lifeline_action_pairs.next() {
+ None => {
+ postamble = Vec::new();
+ },
+ Some( postamble_pair ) => {
+ match parse_amble(gen_ctx, postamble_pair, opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( amble ) => {
+ postamble = amble;
+ }
+ }
+ }
+ }
+ // ***
+ let lf_act = LifelineAction{preamble, lf_id, postamble};
+ return Ok( lf_act );
+}
+
+
diff --git a/src/from_text/action/mod.rs b/src/from_text/action/mod.rs
new file mode 100644
index 0000000..1a2d2ef
--- /dev/null
+++ b/src/from_text/action/mod.rs
@@ -0,0 +1,17 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod action;
+mod amble;
+mod lf_act;
\ No newline at end of file
diff --git a/src/from_text/data/arithmetic.rs b/src/from_text/data/arithmetic.rs
new file mode 100644
index 0000000..7f1cbe2
--- /dev/null
+++ b/src/from_text/data/arithmetic.rs
@@ -0,0 +1,370 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use pest::Parser;
+use pest::iterators::{Pair,Pairs};
+
+
+use crate::core::context::general::GeneralContext;
+
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::builtin::number::{ARITH_FACTOR_SIGN, ARITH_ADD_SIGN};
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::float::TD_Float;
+use crate::core::syntax::data::var_ref::VariableReference;
+
+use crate::from_text::error::HibouParsingError;
+use crate::from_text::parser::*;
+
+#[derive(Clone, PartialEq, Eq)]
+pub enum ParsingNumberKind {
+ Integer,
+ Float
+}
+
+pub fn parse_arith_expr(gen_ctx : &GeneralContext, arth_pair : Pair<Rule>, opt_ms_id : &Option<usize>) -> Result<TD_Generic,HibouParsingError> {
+ let mut pairs = arth_pair.into_inner();
+ let factor_pair = pairs.next().unwrap();
+ // ***
+ let as_raw_string_for_error = factor_pair.as_str().to_string();
+ // ***
+ match parse_factor_expr(gen_ctx,factor_pair,opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( factor_td_gen ) => {
+ match factor_td_gen {
+ TD_Generic::Integer( factor_td_int ) => {
+ let mut adds : Vec<(ARITH_ADD_SIGN,TD_Integer)> = Vec::new();
+ adds.push( (ARITH_ADD_SIGN::Plus,factor_td_int) );
+ while let Some(next_add) = pairs.next() {
+ match parse_add_expr(gen_ctx,next_add,opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (sign,add_td_gen) ) => {
+ match add_td_gen {
+ TD_Generic::Integer( add_td_int ) => {
+ adds.push( (sign,add_td_int) );
+ },
+ _ => {
+ return Err( HibouParsingError::MalformedArithmeticExpression( as_raw_string_for_error ) );
+ }
+ }
+ }
+ }
+ }
+ if adds.len() == 1 {
+ let (_,prim) = adds.get(0).unwrap();
+ return Ok( TD_Generic::Integer(prim.clone()) );
+ } else {
+ return Ok( TD_Generic::Integer( TD_Integer::Add(adds) ) );
+ }
+ },
+ TD_Generic::Float( factor_td_float ) => {
+ let mut adds : Vec<(ARITH_ADD_SIGN,TD_Float)> = Vec::new();
+ adds.push( (ARITH_ADD_SIGN::Plus,factor_td_float) );
+ while let Some(next_add) = pairs.next() {
+ match parse_add_expr(gen_ctx,next_add,opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (sign,add_td_gen) ) => {
+ match add_td_gen {
+ TD_Generic::Float( add_td_float ) => {
+ adds.push( (sign,add_td_float) );
+ },
+ _ => {
+ return Err( HibouParsingError::MalformedArithmeticExpression( as_raw_string_for_error ) );
+ }
+ }
+ }
+ }
+ }
+ if adds.len() == 1 {
+ let(_,prim) = adds.get(0).unwrap();
+ return Ok( TD_Generic::Float(prim.clone()) );
+ } else {
+ return Ok( TD_Generic::Float( TD_Float::Add(adds) ) );
+ }
+ },
+ _ => {
+ return Err( HibouParsingError::MalformedArithmeticExpression( as_raw_string_for_error ) );
+ }
+ }
+ }
+ }
+}
+
+fn parse_add_expr(gen_ctx : &GeneralContext, add_pair : Pair<Rule>, opt_ms_id : &Option<usize>) -> Result<(ARITH_ADD_SIGN,TD_Generic),HibouParsingError> {
+ let mut pairs = add_pair.into_inner();
+ let sign_pair = pairs.next().unwrap();
+ let factor_pair = pairs.next().unwrap();
+ match parse_factor_expr(gen_ctx,factor_pair,opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( factor_td_gen ) => {
+ match sign_pair.as_rule() {
+ Rule::ARITH_PLUS => {
+ return Ok( (ARITH_ADD_SIGN::Plus,factor_td_gen) );
+ },
+ Rule::ARITH_MINUS => {
+ return Ok( (ARITH_ADD_SIGN::Minus,factor_td_gen) );
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+ }
+}
+
+fn parse_primary_expr(gen_ctx : &GeneralContext, primary_pair : Pair<Rule>, opt_ms_id : &Option<usize>) -> Result<TD_Generic,HibouParsingError> {
+ let mut contents = primary_pair.into_inner();
+ let first_pair = contents.next().unwrap();
+ // ***
+ let as_raw_string_for_error = first_pair.as_str().to_string();
+ // ***
+ match first_pair.as_rule() {
+ Rule::ARITH_EXPR => {
+ return parse_arith_expr(gen_ctx,first_pair,opt_ms_id);
+ },
+ Rule::ARITH_FLOAT => {
+ let content_str : String = first_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let my_val : f64 = content_str.parse::<f64>().unwrap();
+ let td_float = TD_Float::Value( my_val );
+ return Ok( TD_Generic::Float(td_float) );
+ },
+ Rule::ARITH_INTEGER => {
+ let content_str : String = first_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let my_val : i64 = content_str.parse::<i64>().unwrap();
+ let td_int = TD_Integer::Value( my_val );
+ return Ok( TD_Generic::Integer(td_int) );
+ },
+ Rule::MSG_PRM_REF => {
+ match opt_ms_id {
+ None => {
+ return Err( HibouParsingError::ParameterUsageError("need contextual message to parse data with message parameter reference".to_string()));
+ },
+ Some( ms_id ) => {
+ match gen_ctx.get_ms_spec(*ms_id) {
+ Err(e) => {
+ panic!();
+ },
+ Ok( ms_spec ) => {
+ let content = first_pair.into_inner().next().unwrap();
+ match content.as_rule() {
+ Rule::PRM_LABEL => {
+ let prm_label : String = content.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let mut idx : usize = 0;
+ for (pr_type,opt_pr_name) in ms_spec {
+ if let Some(got_pr_name) = opt_pr_name {
+ if got_pr_name == prm_label {
+ let var_ref = VariableReference::MSG_PARAMETER(*ms_id,idx);
+ match pr_type {
+ TD_DataType::Integer => {
+ return Ok( TD_Generic::Integer(TD_Integer::Reference(var_ref)) );
+ },
+ TD_DataType::Float => {
+ return Ok( TD_Generic::Float(TD_Float::Reference(var_ref)) );
+ },
+ _ => {
+ return Err( HibouParsingError::MalformedArithmeticExpression( as_raw_string_for_error ) );
+ }
+ }
+ }
+ }
+ idx = idx +1;
+ }
+ return Err(HibouParsingError::ParameterUsageError( format!("no parameter '{}' in message '{}'",prm_label,gen_ctx.get_ms_name(*ms_id).unwrap()) ));
+ },
+ Rule::ARITH_INTEGER => {
+ let pr_id : usize = content.as_str().parse::<usize>().unwrap();
+ match ms_spec.get(pr_id) {
+ None => {
+ return Err(HibouParsingError::ParameterUsageError( format!("no parameter number '{}' in message '{}'",pr_id,gen_ctx.get_ms_name(*ms_id).unwrap()) ));
+ },
+ Some( (pr_type,opt_pr_name) ) => {
+ let var_ref = VariableReference::MSG_PARAMETER(*ms_id,pr_id);
+ match pr_type {
+ TD_DataType::Integer => {
+ return Ok( TD_Generic::Integer(TD_Integer::Reference(var_ref)) );
+ },
+ TD_DataType::Float => {
+ return Ok( TD_Generic::Float(TD_Float::Reference(var_ref)) );
+ },
+ _ => {
+ return Err( HibouParsingError::MalformedArithmeticExpression( as_raw_string_for_error ) );
+ }
+ }
+ }
+ }
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", content.as_rule() );
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ Rule::VAR_LABEL => {
+ let content_str : String = first_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_vr_id(&content_str) {
+ None => {
+ return Err( HibouParsingError::MissingVariableDeclarationError( content_str ) );
+ },
+ Some( vr_id ) => {
+ let var_ref = VariableReference::VARIABLE(vr_id);
+ match gen_ctx.get_vr_type( vr_id ).unwrap() {
+ TD_DataType::Integer => {
+ return Ok( TD_Generic::Integer(TD_Integer::Reference(var_ref)) );
+ },
+ TD_DataType::Float => {
+ return Ok( TD_Generic::Float(TD_Float::Reference(var_ref)) );
+ },
+ _ => {
+ return Err( HibouParsingError::MalformedArithmeticExpression( as_raw_string_for_error ) );
+ }
+ }
+ }
+ }
+ },
+ Rule::ARITH_MINUS => {
+ let second_pair = contents.next().unwrap();
+ match parse_primary_expr(gen_ctx,second_pair,opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( td_gen ) => {
+ match td_gen {
+ TD_Generic::Integer(td_int) => {
+ return Ok( TD_Generic::Integer(TD_Integer::Minus(Box::new(td_int))) );
+ },
+ TD_Generic::Float(td_float) => {
+ return Ok( TD_Generic::Float(TD_Float::Minus(Box::new(td_float))) );
+ },
+ _ => {
+ return Err( HibouParsingError::MalformedArithmeticExpression( as_raw_string_for_error ) );
+ }
+ }
+ }
+ }
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+}
+
+fn parse_factor_expr(gen_ctx : &GeneralContext, factor_pair : Pair<Rule>, opt_ms_id : &Option<usize>) -> Result<TD_Generic,HibouParsingError> {
+ let mut pairs = factor_pair.into_inner();
+ let primary_pair = pairs.next().unwrap();
+ // ***
+ let as_raw_string_for_error = primary_pair.as_str().to_string();
+ // ***
+ match parse_primary_expr(gen_ctx,primary_pair,opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( primary_td_gen ) => {
+ match primary_td_gen {
+ TD_Generic::Integer( primary_td_int ) => {
+ let mut exprs : Vec<(ARITH_FACTOR_SIGN,TD_Integer)> = Vec::new();
+ exprs.push( (ARITH_FACTOR_SIGN::Mult,primary_td_int) );
+ while let Some(next_exp) = pairs.next() {
+ match parse_mult_expr(gen_ctx,next_exp,opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (sign,mult_td_gen) ) => {
+ match mult_td_gen {
+ TD_Generic::Integer( mult_td_int ) => {
+ exprs.push( (sign,mult_td_int) );
+ },
+ _ => {
+ return Err( HibouParsingError::MalformedArithmeticExpression( as_raw_string_for_error ) );
+ }
+ }
+ }
+ }
+ }
+ if exprs.len() == 1 {
+ let (_,prim) = exprs.get(0).unwrap();
+ return Ok( TD_Generic::Integer(prim.clone()) );
+ } else {
+ return Ok( TD_Generic::Integer(TD_Integer::Factor(exprs)));
+ }
+ },
+ TD_Generic::Float( primary_td_float ) => {
+ let mut exprs : Vec<(ARITH_FACTOR_SIGN,TD_Float)> = Vec::new();
+ exprs.push( (ARITH_FACTOR_SIGN::Mult,primary_td_float) );
+ while let Some(next_exp) = pairs.next() {
+ match parse_mult_expr(gen_ctx,next_exp,opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (sign,mult_td_gen) ) => {
+ match mult_td_gen {
+ TD_Generic::Float( mult_td_float ) => {
+ exprs.push( (sign,mult_td_float) );
+ },
+ _ => {
+ return Err( HibouParsingError::MalformedArithmeticExpression( as_raw_string_for_error ) );
+ }
+ }
+ }
+ }
+ }
+ if exprs.len() == 1 {
+ let (_,prim) = exprs.get(0).unwrap();
+ return Ok( TD_Generic::Float( prim.clone() ) );
+ } else {
+ return Ok( TD_Generic::Float(TD_Float::Factor(exprs)));
+ }
+ },
+ _ => {
+ return Err( HibouParsingError::MalformedArithmeticExpression( as_raw_string_for_error ) );
+ }
+ }
+ }
+ }
+}
+
+fn parse_mult_expr(gen_ctx : &GeneralContext, mult_pair : Pair<Rule>, opt_ms_id : &Option<usize>) -> Result<(ARITH_FACTOR_SIGN,TD_Generic),HibouParsingError> {
+ let mut pairs = mult_pair.into_inner();
+ let sign_pair = pairs.next().unwrap();
+ let primary_pair = pairs.next().unwrap();
+ match parse_primary_expr(gen_ctx,primary_pair,opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( primary_td_gen ) => {
+ match sign_pair.as_rule() {
+ Rule::ARITH_MULT => {
+ return Ok( (ARITH_FACTOR_SIGN::Mult,primary_td_gen) );
+ },
+ Rule::ARITH_DIV => {
+ return Ok( (ARITH_FACTOR_SIGN::Div,primary_td_gen) );
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/from_text/data/generic.rs b/src/from_text/data/generic.rs
new file mode 100644
index 0000000..9483114
--- /dev/null
+++ b/src/from_text/data/generic.rs
@@ -0,0 +1,177 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use pest::Parser;
+use pest::iterators::{Pair,Pairs};
+
+
+use crate::core::context::general::GeneralContext;
+
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::builtin::string::TD_String;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::core::syntax::data::builtin::number::{ARITH_FACTOR_SIGN, ARITH_ADD_SIGN};
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::float::TD_Float;
+use crate::core::syntax::data::var_ref::VariableReference;
+
+use crate::from_text::error::HibouParsingError;
+use crate::from_text::parser::*;
+use crate::from_text::data::arithmetic::{ParsingNumberKind,parse_arith_expr};
+use crate::from_text::data::logic::parse_logic_expr;
+
+pub fn parse_data(gen_ctx : &GeneralContext,
+ td_value : Pair<Rule>,
+ opt_ms_id : &Option<usize>) -> Result<TD_Generic,HibouParsingError> {
+ let data_pair = td_value.into_inner().next().unwrap();
+ match data_pair.as_rule() {
+ Rule::MSG_PRM_REF => {
+ match opt_ms_id {
+ None => {
+ return Err( HibouParsingError::ParameterUsageError("need contextual message to parse data with message parameter reference".to_string()));
+ },
+ Some( ms_id ) => {
+ match gen_ctx.get_ms_spec(*ms_id) {
+ Err(e) => {
+ panic!();
+ },
+ Ok( ms_spec ) => {
+ let content = data_pair.into_inner().next().unwrap();
+ match content.as_rule() {
+ Rule::PRM_LABEL => {
+ let prm_label : String = content.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let mut idx : usize = 0;
+ for (pr_type,opt_pr_name) in ms_spec {
+ if let Some(got_pr_name) = opt_pr_name {
+ if got_pr_name == prm_label {
+ let var_ref = VariableReference::MSG_PARAMETER(*ms_id,idx);
+ match pr_type {
+ TD_DataType::Bool => {
+ return Ok( TD_Generic::Bool( TD_Bool::Reference(var_ref) ) );
+ },
+ TD_DataType::Integer => {
+ return Ok( TD_Generic::Integer( TD_Integer::Reference(var_ref) ) );
+ },
+ TD_DataType::Float => {
+ return Ok( TD_Generic::Float( TD_Float::Reference(var_ref) ) );
+ },
+ TD_DataType::String => {
+ return Ok( TD_Generic::String( TD_String::Reference(var_ref) ) );
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+ }
+ idx = idx +1;
+ }
+ return Err(HibouParsingError::ParameterUsageError( format!("no parameter '{}' in message '{}'",prm_label,gen_ctx.get_ms_name(*ms_id).unwrap()) ));
+ },
+ Rule::ARITH_INTEGER => {
+ let pr_id : usize = content.as_str().parse::<usize>().unwrap();
+ match ms_spec.get(pr_id) {
+ None => {
+ return Err(HibouParsingError::ParameterUsageError(format!("missing parameter declaration")));
+ },
+ Some( (pr_type,opt_pr_name) ) => {
+ let var_ref = VariableReference::MSG_PARAMETER(*ms_id,pr_id);
+ match pr_type {
+ TD_DataType::Bool => {
+ return Ok( TD_Generic::Bool( TD_Bool::Reference(var_ref) ) );
+ },
+ TD_DataType::Integer => {
+ return Ok( TD_Generic::Integer( TD_Integer::Reference(var_ref) ) );
+ },
+ TD_DataType::Float => {
+ return Ok( TD_Generic::Float( TD_Float::Reference(var_ref) ) );
+ },
+ TD_DataType::String => {
+ return Ok( TD_Generic::String( TD_String::Reference(var_ref) ) );
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+ }
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", content.as_rule() );
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ Rule::VAR_LABEL => {
+ let var_name : String = data_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_vr_id( &var_name) {
+ None => {
+ return Err( HibouParsingError::MissingVariableDeclarationError(var_name) );
+ },
+ Some( vr_id ) => {
+ match gen_ctx.get_vr_type(vr_id) {
+ Err(_) => {
+ panic!();
+ },
+ Ok( var_type ) => {
+ let var_ref = VariableReference::VARIABLE(vr_id);
+ match var_type {
+ TD_DataType::Bool => {
+ return Ok( TD_Generic::Bool( TD_Bool::Reference(var_ref) ) );
+ },
+ TD_DataType::Integer => {
+ return Ok( TD_Generic::Integer( TD_Integer::Reference(var_ref) ) );
+ },
+ TD_DataType::Float => {
+ return Ok( TD_Generic::Float( TD_Float::Reference(var_ref) ) );
+ },
+ TD_DataType::String => {
+ return Ok( TD_Generic::String( TD_String::Reference(var_ref) ) );
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ Rule::STRING_content => {
+ let string_content = data_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let string_value = TD_String::Value( string_content );
+ return Ok( TD_Generic::String( string_value ));
+ },
+ Rule::ARITH_EXPR => {
+ return parse_arith_expr(gen_ctx, data_pair,opt_ms_id);
+ },
+ Rule::LOGIC_EXPR => {
+ match parse_logic_expr(gen_ctx, data_pair, opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( td_bool ) => {
+ return Ok( TD_Generic::Bool(td_bool) );
+ }
+ }
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", data_pair.as_rule() );
+ }
+ }
+}
diff --git a/src/from_text/data/logic.rs b/src/from_text/data/logic.rs
new file mode 100644
index 0000000..bf13359
--- /dev/null
+++ b/src/from_text/data/logic.rs
@@ -0,0 +1,226 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use pest::Parser;
+use pest::iterators::{Pair,Pairs};
+
+
+use crate::core::context::general::GeneralContext;
+
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::builtin::bool::{TD_Bool,Bool_Compare};
+use crate::core::syntax::data::var_ref::VariableReference;
+
+use crate::from_text::error::HibouParsingError;
+use crate::from_text::parser::*;
+use crate::from_text::data::generic::parse_data;
+
+pub fn parse_logic_expr(gen_ctx : &GeneralContext, logic_pair : Pair<Rule>, opt_ms_id : &Option<usize>) -> Result<TD_Bool,HibouParsingError> {
+ let content = logic_pair.into_inner().next().unwrap();
+ match content.as_rule() {
+ Rule::LOGIC_NOT => {
+ let inner = content.into_inner().next().unwrap();
+ match parse_logic_expr(gen_ctx, inner, opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( inner_td_bool ) => {
+ return Ok( TD_Bool::NOT(Box::new(inner_td_bool)));
+ }
+ }
+ },
+ Rule::LOGIC_AND => {
+ return parse_AND_OR_expr(gen_ctx,content, ParsingLogicKind::AND, opt_ms_id);
+ },
+ Rule::LOGIC_OR => {
+ return parse_AND_OR_expr(gen_ctx,content, ParsingLogicKind::OR, opt_ms_id);
+ },
+ Rule::LOGIC_CMP => {
+ return parse_CMP_expr(gen_ctx, content, opt_ms_id);
+ },
+ Rule::MSG_PRM_REF => {
+ match opt_ms_id {
+ None => {
+ return Err( HibouParsingError::ParameterUsageError("need contextual message to parse data with message parameter reference".to_string()));
+ },
+ Some( ms_id ) => {
+ match gen_ctx.get_ms_spec(*ms_id) {
+ Err(e) => {
+ panic!();
+ },
+ Ok( ms_spec ) => {
+ let content = content.into_inner().next().unwrap();
+ match content.as_rule() {
+ Rule::PRM_LABEL => {
+ let prm_label : String = content.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let mut idx : usize = 0;
+ for (pr_type,opt_pr_name) in ms_spec {
+ if let Some(got_pr_name) = opt_pr_name {
+ if got_pr_name == prm_label {
+ let var_ref = VariableReference::MSG_PARAMETER(*ms_id,idx);
+ match pr_type {
+ TD_DataType::Bool => {
+ return Ok( TD_Bool::Reference(var_ref) );
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+ }
+ idx = idx +1;
+ }
+ return Err(HibouParsingError::ParameterUsageError( format!("no parameter '{}' in message '{}'",prm_label,gen_ctx.get_ms_name(*ms_id).unwrap()) ));
+ },
+ Rule::ARITH_INTEGER => {
+ let pr_id : usize = content.as_str().parse::<usize>().unwrap();
+ match ms_spec.get(pr_id) {
+ None => {
+ return Err(HibouParsingError::ParameterUsageError( format!("no parameter number '{}' in message '{}'",pr_id,gen_ctx.get_ms_name(*ms_id).unwrap()) ));
+ },
+ Some( (pr_type,opt_pr_name) ) => {
+ let var_ref = VariableReference::MSG_PARAMETER(*ms_id,pr_id);
+ match pr_type {
+ TD_DataType::Bool => {
+ return Ok( TD_Bool::Reference(var_ref) );
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+ }
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", content.as_rule() );
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ Rule::VAR_LABEL => {
+ let content_str : String = content.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_vr_id(&content_str) {
+ None => {
+ return Err( HibouParsingError::MissingVariableDeclarationError( content_str ) );
+ },
+ Some( vr_id ) => {
+ let var_ref = VariableReference::VARIABLE(vr_id);
+ match gen_ctx.get_vr_type( vr_id ).unwrap() {
+ TD_DataType::Bool => {
+ return Ok( TD_Bool::Reference(var_ref) );
+ },
+ _ => {
+ return Err( HibouParsingError::MalformedLogicExpression( format!("variable '{}' is not a boolean and appears in a boolean expression",content_str) ));
+ }
+ }
+ }
+ }
+ },
+ Rule::LOGIC_FALSE => {
+ return Ok( TD_Bool::FALSE );
+ },
+ Rule::LOGIC_TRUE => {
+ return Ok( TD_Bool::TRUE );
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+}
+
+enum ParsingLogicKind {
+ AND,
+ OR
+}
+
+
+fn parse_AND_OR_expr(gen_ctx : &GeneralContext, logic_pair : Pair<Rule>, kind : ParsingLogicKind, opt_ms_id : &Option<usize>) -> Result<TD_Bool,HibouParsingError> {
+ let mut pairs = logic_pair.into_inner();
+ let primary_pair = pairs.next().unwrap();
+ match parse_logic_expr(gen_ctx,primary_pair, opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( primary_expr ) => {
+ let mut exprs : Vec<TD_Bool> = Vec::new();
+ exprs.push( primary_expr );
+ while let Some(next_exp) = pairs.next() {
+ match parse_logic_expr(gen_ctx, pairs.next().unwrap(), opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( sub_expr ) => {
+ exprs.push( sub_expr );
+ }
+ }
+ }
+ match kind {
+ ParsingLogicKind::AND => {
+ return Ok( TD_Bool::AND(exprs) );
+ },
+ ParsingLogicKind::OR => {
+ return Ok( TD_Bool::OR(exprs) );
+ }
+ }
+ }
+ }
+}
+
+fn parse_CMP_expr(gen_ctx : &GeneralContext, logic_pair : Pair<Rule>, opt_ms_id : &Option<usize>) -> Result<TD_Bool,HibouParsingError> {
+ let mut inner = logic_pair.into_inner();
+ let val1_pair = inner.next().unwrap();
+ let cmp_operator_pair = inner.next().unwrap();
+ let val2_pair = inner.next().unwrap();
+ match parse_data(gen_ctx,val1_pair,opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( val1 ) => {
+ match parse_data(gen_ctx, val2_pair,opt_ms_id) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( val2 ) => {
+ match cmp_operator_pair.as_rule() {
+ Rule::LOGIC_SYMB_Diff => {
+ return Ok( TD_Bool::COMPARE(Bool_Compare::Different, Box::new(val1), Box::new(val2)) );
+ },
+ Rule::LOGIC_SYMB_E => {
+ return Ok( TD_Bool::COMPARE(Bool_Compare::Equal, Box::new(val1), Box::new(val2)) );
+ },
+ Rule::LOGIC_SYMB_GoE => {
+ return Ok( TD_Bool::COMPARE(Bool_Compare::GreaterOrEqual, Box::new(val1), Box::new(val2)) );
+ },
+ Rule::LOGIC_SYMB_G => {
+ return Ok( TD_Bool::COMPARE(Bool_Compare::Greater, Box::new(val1), Box::new(val2)) );
+ },
+ Rule::LOGIC_SYMB_LoE => {
+ return Ok( TD_Bool::COMPARE(Bool_Compare::LowerOrEqual, Box::new(val1), Box::new(val2)) );
+ },
+ Rule::LOGIC_SYMB_L => {
+ return Ok( TD_Bool::COMPARE(Bool_Compare::Lower, Box::new(val1), Box::new(val2)) );
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/from_text/data/mod.rs b/src/from_text/data/mod.rs
new file mode 100644
index 0000000..585c008
--- /dev/null
+++ b/src/from_text/data/mod.rs
@@ -0,0 +1,18 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod td_type;
+pub mod generic;
+pub mod logic;
+pub mod arithmetic;
\ No newline at end of file
diff --git a/src/from_text/data/td_type.rs b/src/from_text/data/td_type.rs
new file mode 100644
index 0000000..d05c9b1
--- /dev/null
+++ b/src/from_text/data/td_type.rs
@@ -0,0 +1,41 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use pest::iterators::Pair;
+
+use crate::from_text::parser::*;
+use crate::core::syntax::data::td_type::TD_DataType;
+
+pub fn parse_type(type_pair : Pair<Rule>) -> (TD_DataType,bool) {
+ match type_pair.as_rule() {
+ Rule::DATA_TYPE_Clock => {
+ return (TD_DataType::Float,true);
+ },
+ Rule::DATA_TYPE_Bool => {
+ return (TD_DataType::Bool,false);
+ },
+ Rule::DATA_TYPE_Integer => {
+ return (TD_DataType::Integer,false);
+ },
+ Rule::DATA_TYPE_Float => {
+ return (TD_DataType::Float,false);
+ },
+ Rule::DATA_TYPE_String => {
+ return (TD_DataType::String,false);
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", type_pair.as_rule() );
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/from_text/error.rs b/src/from_text/error.rs
new file mode 100644
index 0000000..a90c0a8
--- /dev/null
+++ b/src/from_text/error.rs
@@ -0,0 +1,102 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::fmt;
+
+use crate::core::syntax::data::td_type::TD_DataType;
+
+#[derive(Debug)]
+pub enum HibouParsingError {
+ FileFormatError(String,String),
+ FileError(String),
+ MatchError(String),
+ // ***
+ MissingMessageDeclarationError(String),
+ MissingLifelineDeclarationError(String),
+ MissingVariableDeclarationError(String),
+ // ***
+ ParameterUsageError(String),
+ // ***
+ MalformedArithmeticExpression(String),
+ MalformedLogicExpression(String),
+ ClockMisuse(String),
+ // ***
+ UnknownMessageParameter(String,usize),
+ WrongMessageParameterType(TD_DataType,TD_DataType,String,String),
+ WrongMessageParametersNumber(usize,usize,String),
+ TimedTraceAbsentDelay(String),
+ // ***
+ NonDisjointTraceComponents,
+ HsfSetupError(String)
+}
+
+impl fmt::Display for HibouParsingError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ HibouParsingError::FileFormatError( got, expected) => {
+ return write!(f, "{}", format!("expected '.{}' file and got '.{}' file", expected, got));
+ },
+ HibouParsingError::FileError(sub_e) => {
+ return write!(f, "{}", format!("error while reading SD conf file : {:}", sub_e));
+ },
+ HibouParsingError::MatchError(sub_e) => {
+ return write!(f, "{}", format!("error while parsing SD string : {:}", sub_e));
+ },
+ HibouParsingError::MissingMessageDeclarationError(sub_e) => {
+ return write!(f, "{}", format!("error while parsing ; missing message declaration : {:}", sub_e));
+ },
+ HibouParsingError::MissingLifelineDeclarationError(sub_e) => {
+ return write!(f, "{}", format!("error while parsing ; missing lifeline declaration : {:}", sub_e));
+ },
+ HibouParsingError::MissingVariableDeclarationError(sub_e) => {
+ return write!(f, "{}", format!("error while parsing ; missing variable declaration : {:}", sub_e));
+ },
+ HibouParsingError::ParameterUsageError(sub_e) => {
+ return write!(f, "{}", format!("error while parsing ; wrong parameter usage : {:}", sub_e));
+ },
+ HibouParsingError::MalformedArithmeticExpression(sub_e) => {
+ return write!(f, "{}", format!("error while parsing ; malformed arithmetic expression : {:}", sub_e));
+ },
+ HibouParsingError::MalformedLogicExpression(sub_e) => {
+ return write!(f, "{}", format!("error while parsing ; malformed logic expression : {:}", sub_e));
+ },
+ HibouParsingError::ClockMisuse(sub_e) => {
+ return write!(f, "{}", format!("error while parsing ; clock misuse : {:}", sub_e));
+ },
+ HibouParsingError::UnknownMessageParameter(ms_name,param_id) => {
+ return write!(f, "{}", format!("error while parsing; unknown message parameter : message {} does not have parameter number {}", ms_name, param_id));
+ },
+ HibouParsingError::WrongMessageParameterType(expected, got, ms_name, ms_specs) => {
+ return write!(f, "{}", format!("error while parsing trace; wrong message parameter type : expected {:?} - got {:?} - in message {:} - with specs {:}", expected, got, ms_name, ms_specs));
+ },
+ HibouParsingError::WrongMessageParametersNumber(expected, got, sub_e) => {
+ return write!(f, "{}", format!("error while parsing trace; wrong message parameters numbers : expected {:?} - got {:?} - in message {:}", expected, got, sub_e));
+ },
+ HibouParsingError::TimedTraceAbsentDelay(sub_e) => {
+ return write!(f, "{}", format!("error while parsing trace; timed trace absent delay : {:}", sub_e));
+ },
+ HibouParsingError::NonDisjointTraceComponents => {
+ return write!(f, "{}", format!("error while parsing ; non disjoint trace canals"));
+ },
+ HibouParsingError::HsfSetupError(sub_e) => {
+ return write!(f, "{}", format!("error while parsing setup section of .hsf file : {:}", sub_e));
+ }
+ }
+ }
+}
+
+
+
+
+
diff --git a/src/from_text/hibou_options.rs b/src/from_text/hibou_options.rs
new file mode 100644
index 0000000..4bb2ae2
--- /dev/null
+++ b/src/from_text/hibou_options.rs
@@ -0,0 +1,284 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::fs;
+use std::collections::{HashSet,HashMap};
+use std::collections::btree_map::BTreeMap;
+use std::path::Path;
+
+use pest::iterators::Pair;
+
+use crate::pest::Parser;
+
+use crate::core::syntax::interaction::Interaction;
+use crate::core::syntax::action::*;
+use crate::core::context::general::GeneralContext;
+
+
+use crate::from_text::error::HibouParsingError;
+use crate::process::log::ProcessLogger;
+
+use crate::from_text::parser::*;
+use crate::rendering::process::graphic_logger::*;
+use crate::process::hibou_process::*;
+
+use crate::process::verdicts::GlobalVerdict;
+use crate::process::process_manager::ProcessPriorities;
+use crate::from_text::hsf_file::ProcessKind;
+
+
+pub struct HibouOptions {
+ pub loggers : Vec<Box<dyn ProcessLogger>>,
+ pub strategy : HibouSearchStrategy,
+ pub pre_filters : Vec<HibouPreFilter>,
+ pub temporality : HibouProcessTemporality,
+ pub goal : Option<GlobalVerdict>,
+ pub frontier_priorities : ProcessPriorities
+}
+
+
+
+impl HibouOptions {
+ pub fn new(loggers : Vec<Box<dyn ProcessLogger>>,
+ strategy : HibouSearchStrategy,
+ pre_filters : Vec<HibouPreFilter>,
+ temporality : HibouProcessTemporality,
+ goal:Option<GlobalVerdict>,
+ frontier_priorities : ProcessPriorities) -> HibouOptions {
+ return HibouOptions{loggers,strategy,pre_filters,temporality,goal,frontier_priorities};
+ }
+
+ pub fn default_explore() -> HibouOptions {
+ return HibouOptions{loggers:Vec::new(),
+ strategy:HibouSearchStrategy::BFS,
+ pre_filters:vec![HibouPreFilter::MaxLoopInstanciation(1)],
+ temporality:HibouProcessTemporality::UnTimed,
+ goal:None,
+ frontier_priorities:ProcessPriorities::new(0,0,0)};
+ }
+
+ pub fn default_analyze() -> HibouOptions {
+ return HibouOptions{loggers:Vec::new(),
+ strategy:HibouSearchStrategy::BFS,
+ pre_filters:Vec::new(),
+ temporality:HibouProcessTemporality::UnTimed,
+ goal:Some(GlobalVerdict::Pass),
+ frontier_priorities:ProcessPriorities::new(0,0,0)};
+ }
+}
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+enum LoggerKinds {
+ graphic
+}
+
+pub fn parse_hibou_options(option_pair : Pair<Rule>,
+ file_name : &str,
+ process_kind : &ProcessKind) -> Result<HibouOptions,HibouParsingError> {
+ let mut loggers : Vec<Box<dyn ProcessLogger>> = Vec::new();
+ let mut strategy : HibouSearchStrategy = HibouSearchStrategy::BFS;
+ let mut frontier_priorities = ProcessPriorities::new(0,0,0);
+ let mut pre_filters : Vec<HibouPreFilter> = Vec::new();
+ let mut temporality : HibouProcessTemporality = HibouProcessTemporality::UnTimed;
+ let mut goal : Option<GlobalVerdict> = None;
+ // ***
+ let mut got_loggers : bool = false;
+ let mut got_strategy : bool = false;
+ let mut got_frontier_priorities : bool = false;
+ let mut got_pre_filters : bool = false;
+ let mut got_temporality : bool = false;
+ let mut got_goal : bool = false;
+ // ***
+ let mut declared_loggers : HashSet<LoggerKinds> = HashSet::new();
+ // ***
+ for option_decl_pair in option_pair.into_inner() {
+ match option_decl_pair.as_rule() {
+ Rule::OPTION_TEMPORALITY_TIMED => {
+ if got_temporality {
+ return Err( HibouParsingError::HsfSetupError("several 'temporality=[X]' declared in the same '@X_option' section".to_string()));
+ }
+ got_temporality = true;
+ temporality = HibouProcessTemporality::Timed;
+ },
+ Rule::OPTION_TEMPORALITY_UNTIMED => {
+ if got_temporality {
+ return Err( HibouParsingError::HsfSetupError("several 'temporality=[X]' declared in the same '@X_option' section".to_string()));
+ }
+ got_temporality = true;
+ temporality = HibouProcessTemporality::UnTimed;
+ },
+ Rule::OPTION_LOGGER_DECL => {
+ if got_loggers {
+ return Err( HibouParsingError::HsfSetupError("several 'loggers=[X]' declared in the same '@X_option' section".to_string()));
+ }
+ got_loggers = true;
+ // ***
+ for logger_kind_pair in option_decl_pair.into_inner() {
+ match logger_kind_pair.as_rule() {
+ Rule::OPTION_GRAPHIC_LOGGER => {
+ if declared_loggers.contains(&LoggerKinds::graphic) {
+ return Err( HibouParsingError::HsfSetupError("several 'graphic' loggers declared in the same '@X_option' section".to_string()));
+ }
+ declared_loggers.insert( LoggerKinds::graphic );
+ let graphic_logger_pair = logger_kind_pair.into_inner().next();
+ match graphic_logger_pair {
+ None => {
+ loggers.push(Box::new(GraphicProcessLogger::new(file_name.to_string(),GraphicProcessLoggerKind::png ) ) );
+ },
+ Some(graphic_logger_kind_pair) => {
+ match graphic_logger_kind_pair.as_rule() {
+ Rule::GRAPHIC_LOGGER_KIND_png => {
+ loggers.push(Box::new(GraphicProcessLogger::new(file_name.to_string(),GraphicProcessLoggerKind::png ) ) );
+ },
+ Rule::GRAPHIC_LOGGER_KIND_svg => {
+ loggers.push(Box::new(GraphicProcessLogger::new(file_name.to_string(),GraphicProcessLoggerKind::svg ) ) );
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", graphic_logger_kind_pair.as_rule() );
+ }
+ }
+ }
+ }
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", logger_kind_pair.as_rule() );
+ }
+ }
+ }
+ },
+ Rule::OPTION_STRATEGY_DECL => {
+ if got_strategy {
+ return Err( HibouParsingError::HsfSetupError("several 'strategy=X' declared in the same '@X_option' section".to_string()));
+ }
+ got_strategy = true;
+ // ***
+ let strategy_pair = option_decl_pair.into_inner().next().unwrap();
+ match strategy_pair.as_rule() {
+ Rule::OPTION_STRATEGY_BFS => {
+ strategy = HibouSearchStrategy::BFS;
+ },
+ Rule::OPTION_STRATEGY_DFS => {
+ strategy = HibouSearchStrategy::DFS;
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", strategy_pair.as_rule() );
+ }
+ }
+ },
+ Rule::OPTION_PRIORITIES_DECL => {
+ if got_frontier_priorities {
+ return Err( HibouParsingError::HsfSetupError("several 'frontier_priorities=X' declared in the same '@X_option' section".to_string()));
+ }
+ got_frontier_priorities = true;
+ // ***
+ for priority_pair in option_decl_pair.into_inner() {
+ let mut priority_contents = priority_pair.into_inner();
+ let priority_kind_pair = priority_contents.next().unwrap();
+ // ***
+ let priority_level_pair = priority_contents.next().unwrap();
+ let priority_level_str : String = priority_level_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let priority_level : i32 = priority_level_str.parse::<i32>().unwrap();
+ // ***
+ match priority_kind_pair.as_rule() {
+ Rule::OPTION_PRIORITTY_emission => {
+ frontier_priorities.emission = priority_level;
+ },
+ Rule::OPTION_PRIORITTY_reception => {
+ frontier_priorities.reception = priority_level;
+ },
+ Rule::OPTION_PRIORITY_loop => {
+ frontier_priorities.in_loop = priority_level;
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", priority_kind_pair.as_rule() );
+ }
+ }
+ }
+ },
+ Rule::OPTION_PREFILTERS_DECL => {
+ if got_pre_filters {
+ return Err( HibouParsingError::HsfSetupError("several 'pre_filters=[X]' declared in the same '@X_option' section".to_string()));
+ }
+ got_pre_filters = true;
+ // ***
+ for pre_filter_pair in option_decl_pair.into_inner() {
+ match pre_filter_pair.as_rule() {
+ Rule::OPTION_PREFILTER_MAX_DEPTH => {
+ let content = pre_filter_pair.into_inner().next().unwrap();
+ let content_str : String = content.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let my_val : u32 = content_str.parse::<u32>().unwrap();
+ pre_filters.push(HibouPreFilter::MaxProcessDepth(my_val));
+ },
+ Rule::OPTION_PREFILTER_MAX_LOOP_DEPTH => {
+ let content = pre_filter_pair.into_inner().next().unwrap();
+ let content_str : String = content.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let my_val : u32 = content_str.parse::<u32>().unwrap();
+ pre_filters.push(HibouPreFilter::MaxLoopInstanciation(my_val));
+ },
+ Rule::OPTION_PREFILTER_MAX_NODE_NUMBER => {
+ let content = pre_filter_pair.into_inner().next().unwrap();
+ let content_str : String = content.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let my_val : u32 = content_str.parse::<u32>().unwrap();
+ pre_filters.push(HibouPreFilter::MaxNodeNumber(my_val));
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", pre_filter_pair.as_rule() );
+ }
+ }
+ }
+ },
+ Rule::OPTION_GOAL_DECL => {
+ if got_goal {
+ return Err( HibouParsingError::HsfSetupError("several 'goal=X' declared in the same '@X_option' section".to_string()));
+ }
+ got_goal = true;
+ // ***
+ let goal_pair = option_decl_pair.into_inner().next().unwrap();
+ match goal_pair.as_rule() {
+ Rule::OPTION_GOAL_pass => {
+ goal = Some( GlobalVerdict::Pass );
+ },
+ Rule::OPTION_GOAL_weakpass => {
+ goal = Some( GlobalVerdict::WeakPass );
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", goal_pair.as_rule() );
+ }
+ }
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", option_decl_pair.as_rule() );
+ }
+ }
+ }
+
+ match process_kind {
+ ProcessKind::Analyze => {
+ let ana_goal : GlobalVerdict;
+ match goal {
+ None => {
+ ana_goal = GlobalVerdict::Pass;
+ },
+ Some( goal_in ) => {
+ ana_goal = goal_in;
+ }
+ }
+ // ***
+ return Ok( HibouOptions::new(loggers,strategy,pre_filters,temporality, Some(ana_goal),frontier_priorities) );
+ },
+ _ => {
+ return Ok( HibouOptions::new(loggers,strategy,pre_filters,temporality, None,frontier_priorities) );
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/from_text/hsf_file.rs b/src/from_text/hsf_file.rs
new file mode 100644
index 0000000..fb86569
--- /dev/null
+++ b/src/from_text/hsf_file.rs
@@ -0,0 +1,188 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::fs;
+use std::collections::{HashSet,HashMap};
+use std::collections::btree_map::BTreeMap;
+use std::path::Path;
+
+use pest::iterators::Pair;
+
+use crate::pest::Parser;
+
+use crate::core::syntax::interaction::Interaction;
+use crate::core::syntax::action::*;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::var_ref::VariableReference;
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::builtin::float::TD_Float;
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::string::TD_String;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::from_text::error::HibouParsingError;
+use crate::process::log::ProcessLogger;
+
+use crate::from_text::parser::*;
+use crate::from_text::data::td_type::parse_type;
+use crate::from_text::interaction::parse_interaction;
+use crate::from_text::data::generic::parse_data;
+use crate::from_text::hibou_options::{HibouOptions,parse_hibou_options};
+
+use crate::process::hibou_process::HibouPreFilter;
+use crate::from_text::setup::{InterpretationItemPlan,parse_setup};
+
+pub static HIBOU_MODEL_FILE_EXTENSION : &'static str = "hsf";
+
+pub enum ProcessKind {
+ Explore,
+ Analyze,
+ None
+}
+
+pub fn parse_hsf_file(file_path : &str, process_kind : &ProcessKind) -> Result<(GeneralContext,ExecutionContext,Interaction,HibouOptions),HibouParsingError> {
+ let path_object = Path::new(file_path);
+ let file_extension : &str = path_object.extension().unwrap().to_str().unwrap();
+ if file_extension != HIBOU_MODEL_FILE_EXTENSION {
+ return Err( HibouParsingError::FileFormatError(file_extension.to_string(),HIBOU_MODEL_FILE_EXTENSION.to_string()));
+ }
+ let file_name : &str = path_object.file_stem().unwrap().to_str().unwrap();
+ match fs::read_to_string(file_path) {
+ Ok( unparsed_hsf_str ) => {
+ return parse_hsf_string(unparsed_hsf_str, file_name, process_kind);
+ },
+ Err(e) => {
+ return Err( HibouParsingError::FileError(e.to_string()) );
+ }
+ }
+}
+
+pub fn parse_hsf_string(sd_string : String,
+ name : &str,
+ process_kind : &ProcessKind) -> Result<(GeneralContext,ExecutionContext,Interaction,HibouOptions),HibouParsingError> {
+ match SDParser::parse(Rule::HSF_PEST_FILE, &sd_string) {
+ Ok( ref mut sd_cfg_pair ) => {
+ let mut content = sd_cfg_pair.next().unwrap().into_inner();
+ let first_pair = content.next().unwrap();
+ match first_pair.as_rule() {
+ Rule::HIBOU_MODEL_SETUP => {
+ let second_pair = content.next().unwrap();
+ return parse_sd(second_pair,Some(first_pair),name,process_kind);
+ },
+ Rule::SD_INTERACTION => {
+ return parse_sd(first_pair, None,name,process_kind);
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+ },
+ Err(e) => {
+ return Err( HibouParsingError::MatchError(e.to_string()) );
+ }
+ }
+}
+
+
+fn parse_sd(interaction_pair : Pair<Rule>,
+ setup_pair_opt : Option< Pair<Rule> >,
+ name : &str,
+ process_kind : &ProcessKind)
+ -> Result<(GeneralContext,ExecutionContext,Interaction,HibouOptions),HibouParsingError> {
+ let mut gen_ctx = GeneralContext::new();
+ let interpretation_plan : Vec<InterpretationItemPlan>;
+ let hibou_options : HibouOptions;
+ match setup_pair_opt {
+ None => {
+ interpretation_plan = Vec::new();
+ match process_kind {
+ ProcessKind::Analyze => {
+ hibou_options = HibouOptions::default_analyze();
+ },
+ _ => {
+ hibou_options = HibouOptions::default_explore();
+ }
+ }
+ },
+ Some( setup_pair ) => {
+ match parse_setup(setup_pair, &mut gen_ctx, name, process_kind) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (intplan, hoptions) ) => {
+ interpretation_plan = intplan;
+ hibou_options = hoptions;
+ }
+ }
+ }
+ }
+ match parse_interaction(&gen_ctx, interaction_pair) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( interaction ) => {
+ let mut interpretation : BTreeMap<usize, BTreeMap<usize,TD_Generic> > = BTreeMap::new();
+ let mut symb_count : usize = 1;
+ let mut symb_types : BTreeMap<usize,TD_DataType> = BTreeMap::new();
+ for iip in interpretation_plan {
+ let mut interpretation_on_lf : BTreeMap<usize,TD_Generic>;
+ match interpretation.get(&iip.lf_id) {
+ None => {
+ interpretation_on_lf = BTreeMap::new();
+ },
+ Some( got_lf_interpretation ) => {
+ interpretation_on_lf = got_lf_interpretation.clone();
+ }
+ }
+ // ***
+ match &iip.assignment {
+ ValueOrNewFresh::Value( ref td_generic ) => {
+ interpretation_on_lf.insert( iip.vr_id, td_generic.clone() );
+ },
+ ValueOrNewFresh::NewFresh => {
+ match gen_ctx.get_vr_type(iip.vr_id) {
+ Err(e) => {
+ panic!();
+ },
+ Ok( vr_type ) => {
+ let sy_ref = VariableReference::SYMBOL(symb_count);
+ match vr_type {
+ TD_DataType::Float => {
+ interpretation_on_lf.insert( iip.vr_id, TD_Generic::Float( TD_Float::Reference(sy_ref)) );
+ },
+ TD_DataType::Integer => {
+ interpretation_on_lf.insert( iip.vr_id, TD_Generic::Integer( TD_Integer::Reference(sy_ref)) );
+ },
+ TD_DataType::Bool => {
+ interpretation_on_lf.insert( iip.vr_id, TD_Generic::Bool( TD_Bool::Reference(sy_ref)) );
+ },
+ TD_DataType::String => {
+ interpretation_on_lf.insert( iip.vr_id, TD_Generic::String( TD_String::Reference(sy_ref)) );
+ }
+ }
+ symb_types.insert(symb_count, vr_type);
+ symb_count = symb_count +1;
+ }
+ }
+ }
+ }
+ interpretation.insert( iip.lf_id, interpretation_on_lf);
+ }
+ let exe_ctx = ExecutionContext::new(&gen_ctx,interpretation,symb_count);
+ return Ok( (gen_ctx,exe_ctx,interaction.decorate_with_initial_positions(Vec::new() ),hibou_options) );
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/from_text/htf_file.rs b/src/from_text/htf_file.rs
new file mode 100644
index 0000000..8b5a5f2
--- /dev/null
+++ b/src/from_text/htf_file.rs
@@ -0,0 +1,359 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::path::Path;
+use std::collections::{HashMap,HashSet};
+use std::fs;
+use pest::Parser;
+use pest::iterators::{Pair,Pairs};
+use std::iter::FromIterator;
+
+use crate::core::trace::*;
+use crate::core::context::general::GeneralContext;
+
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::from_text::error::HibouParsingError;
+
+use crate::from_text::parser::*;
+
+use crate::process::hibou_process::HibouProcessTemporality;
+
+use crate::from_text::data::generic::parse_data;
+
+use crate::core::syntax::data::builtin::float::TD_Float;
+
+pub static HIBOU_TRACE_FILE_EXTENSION : &'static str = "htf";
+
+pub fn parse_htf_file(file_path : &str,
+ gen_ctx : &GeneralContext,
+ temporality : &HibouProcessTemporality) -> Result<AnalysableMultiTrace,HibouParsingError> {
+ let path_object = Path::new(file_path);
+ let file_extension : &str = path_object.extension().unwrap().to_str().unwrap();
+ if file_extension != HIBOU_TRACE_FILE_EXTENSION {
+ return Err( HibouParsingError::FileFormatError(file_extension.to_string(),HIBOU_TRACE_FILE_EXTENSION.to_string()));
+ }
+ let file_name : &str = path_object.file_stem().unwrap().to_str().unwrap();
+ match fs::read_to_string(file_path) {
+ Ok( unparsed_htf_str ) => {
+ return multitrace_from_text(&unparsed_htf_str, gen_ctx, temporality);
+ },
+ Err(e) => {
+ return Err( HibouParsingError::FileError(e.to_string()) );
+ }
+ }
+}
+
+fn complete_canals_up_to_defined_lifelines(canals : &mut Vec<MultiTraceCanal>, gen_ctx : &GeneralContext) {
+ let mut rem_lifelines : HashSet<usize> = HashSet::from_iter((0..gen_ctx.get_lf_num()).collect::<Vec<usize>>().iter().cloned());
+ for canal in canals.iter() {
+ for lf_id in &canal.lifelines {
+ rem_lifelines.remove(lf_id);
+ }
+ }
+ // ***
+ for lf_id in rem_lifelines {
+ let lifelines : HashSet<usize> = HashSet::from_iter( vec![lf_id].iter().cloned() );
+ let trace : Vec<TraceAction> = Vec::new();
+ canals.push( MultiTraceCanal{lifelines,trace})
+ }
+ // ***
+}
+
+pub fn multitrace_from_text(multitrace_str : &String,
+ gen_ctx : &GeneralContext,
+ temporality : &HibouProcessTemporality) -> Result<AnalysableMultiTrace,HibouParsingError> {
+ match SDParser::parse(Rule::HTF_PEST_FILE, multitrace_str) {
+ Err(e) => {
+ panic!(e);
+ },
+ Ok( ref mut htf_pair ) => {
+ let mut content = htf_pair.next().unwrap().into_inner();
+ let first_pair : Pair<Rule> = content.next().unwrap();
+ match first_pair.as_rule() {
+ Rule::TRACE => {
+ let mut canals : Vec<MultiTraceCanal> = Vec::new();
+ match trace_canal_from_pair(first_pair,gen_ctx,&HashSet::new(),temporality) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( trace_canal ) => {
+ canals.push( trace_canal );
+ }
+ }
+ complete_canals_up_to_defined_lifelines(&mut canals,gen_ctx);
+ return Ok( AnalysableMultiTrace::new(canals) );
+ },
+ Rule::MULTI_TRACE => {
+ let mut unavailable_lifelines : HashSet<usize> = HashSet::new();
+ let mut canals : Vec<MultiTraceCanal> = Vec::new();
+ for trace_pair in first_pair.into_inner() {
+ match trace_canal_from_pair(trace_pair,gen_ctx,&unavailable_lifelines,temporality) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( trace_canal ) => {
+ unavailable_lifelines = unavailable_lifelines.union( &trace_canal.lifelines ).cloned().collect();
+ canals.push( trace_canal );
+ }
+ }
+ }
+ complete_canals_up_to_defined_lifelines(&mut canals,gen_ctx);
+ return Ok( AnalysableMultiTrace::new(canals) );
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", first_pair.as_rule() );
+ }
+ }
+ }
+ }
+}
+
+pub fn trace_canal_from_pair(trace_pair : Pair<Rule>,
+ gen_ctx : &GeneralContext,
+ unavailable_lifelines : &HashSet<usize>,
+ temporality : &HibouProcessTemporality) -> Result<MultiTraceCanal,HibouParsingError> {
+ let mut trace : Vec<TraceAction> = Vec::new();
+ let mut lifelines : HashSet<usize> = HashSet::new();
+ // ***
+ let mut content = trace_pair.into_inner();
+ // ***
+ match content.next() {
+ None => {},
+ Some( first_pair ) => {
+ match first_pair.as_rule() {
+ Rule::CANAL_ANY => {
+ match inner_trace_from_pairs(&mut content,gen_ctx,unavailable_lifelines,&mut trace, &mut lifelines, true,temporality) {
+ Ok( _ ) => {
+ // do nothing
+ },
+ Err(e) => {
+ return Err(e);
+ }
+ };
+ },
+ Rule::CANAL_ALL => {
+ let all_lfs : HashSet<usize> = HashSet::from_iter((0..gen_ctx.get_lf_num()).collect::<Vec<usize>>().iter().cloned());
+ lifelines = all_lfs;
+ match inner_trace_from_pairs(&mut content,gen_ctx,unavailable_lifelines,&mut trace, &mut lifelines, true,temporality) {
+ Ok( _ ) => {
+ // do nothing
+ },
+ Err(e) => {
+ return Err(e);
+ }
+ };
+ },
+ Rule::CANAL_LIFELINES => {
+ for trace_lf_pair in first_pair.into_inner() {
+ let lf_name : String = trace_lf_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_lf_id(&lf_name) {
+ None => {
+ return Err( HibouParsingError::MissingLifelineDeclarationError(lf_name));
+ },
+ Some( lf_id ) => {
+ lifelines.insert(lf_id);
+ }
+ }
+ }
+ match inner_trace_from_pairs(&mut content,gen_ctx,unavailable_lifelines,&mut trace, &mut lifelines, false,temporality) {
+ Ok( _ ) => {
+ // do nothing
+ },
+ Err(e) => {
+ return Err(e);
+ }
+ };
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", first_pair.as_rule() );
+ }
+ }
+ }
+ }
+ // ***
+ return Ok( MultiTraceCanal{lifelines,trace} );
+}
+
+pub fn inner_trace_from_pairs(content : &mut Pairs<Rule>,
+ gen_ctx : &GeneralContext,
+ unavailable_lifelines : &HashSet<usize>,
+ trace : &mut Vec<TraceAction>,
+ lifelines : &mut HashSet<usize>,
+ add_lfs : bool,
+ temporality : &HibouProcessTemporality) -> Result<(),HibouParsingError> {
+ for action_pair in content {
+ match trace_action_from_text(action_pair,gen_ctx,temporality) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( action ) => {
+ if unavailable_lifelines.contains(&action.lf_id) {
+ return Err( HibouParsingError::NonDisjointTraceComponents );
+ } else {
+ if add_lfs {
+ lifelines.insert( action.lf_id);
+ }
+ }
+ trace.push( action );
+ }
+ }
+ }
+ return Ok( () );
+}
+
+
+fn trace_action_from_text(action_pair : Pair<Rule>,
+ gen_ctx : &GeneralContext,
+ temporality : &HibouProcessTemporality) -> Result<TraceAction,HibouParsingError> {
+ let original_pair_as_string = action_pair.as_str().to_string();
+ // ***
+ let mut raw_delay_opt : Option<f64> = None;
+ // ***
+ let mut contents = action_pair.into_inner();
+ // ***
+ let first_pair : Pair<Rule> = contents.next().unwrap();
+ let lf_pair : Pair<Rule>;
+ match first_pair.as_rule() {
+ Rule::TRACE_DELAY => {
+ let inner_float_pair = first_pair.into_inner().next().unwrap();
+ let content_str : String = inner_float_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ raw_delay_opt = Some( content_str.parse::<f64>().unwrap() );
+ lf_pair = contents.next().unwrap()
+ },
+ Rule::TRACE_LIFELINE => {
+ lf_pair = first_pair;
+ },
+ _ => {
+ panic!();
+ }
+ }
+ // ***
+ match untimed_trace_action_from_text(lf_pair, &mut contents, gen_ctx) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (lf_id,act_kind,ms_id,arguments) ) => {
+ match raw_delay_opt {
+ None => {
+ match temporality {
+ HibouProcessTemporality::UnTimed => {
+ return Ok( TraceAction{delay:None,lf_id,act_kind,ms_id,arguments} );
+ },
+ HibouProcessTemporality::Timed => {
+ return Err( HibouParsingError::TimedTraceAbsentDelay(original_pair_as_string) );
+ }
+ }
+ },
+ Some( raw_delay ) => {
+ match temporality {
+ HibouProcessTemporality::UnTimed => {
+ println!("WARNNG : unused timed trace delay information due to analysis in untimed mode");
+ return Ok( TraceAction{delay:None,lf_id,act_kind,ms_id,arguments} );
+ },
+ HibouProcessTemporality::Timed => {
+ return Ok( TraceAction{delay:Some(TD_Float::Value(raw_delay)),lf_id,act_kind,ms_id,arguments} );
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+fn untimed_trace_action_from_text( lf_pair : Pair<Rule>,
+ action_contents : &mut Pairs<Rule>,
+ gen_ctx : &GeneralContext) -> Result<(usize,TraceActionKind,usize,Vec<TD_Generic>),HibouParsingError> {
+ // ***
+ let lf_name : String = lf_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_lf_id(&lf_name) {
+ None => {
+ return Err( HibouParsingError::MissingLifelineDeclarationError(lf_name) );
+ },
+ Some( lf_id ) => {
+ // ***
+ let act_kind_pair : Pair<Rule> = action_contents.next().unwrap();
+ let act_kind : TraceActionKind;
+ match act_kind_pair.as_rule() {
+ Rule::TRACE_EMISSION_SYMBOL => {
+ act_kind = TraceActionKind::Emission;
+ },
+ Rule::TRACE_RECEPTION_SYMBOL => {
+ act_kind = TraceActionKind::Reception;
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", act_kind_pair.as_rule() );
+ }
+ }
+ // ***
+ let ms_pair : Pair<Rule> = action_contents.next().unwrap();
+ let ms_name : String = ms_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_ms_id(&ms_name) {
+ None => {
+ return Err( HibouParsingError::MissingMessageDeclarationError(ms_name) );
+ },
+ Some( ms_id ) => {
+ let ms_specs = gen_ctx.get_ms_spec(ms_id).unwrap();
+ // ***
+ let mut arg_count : usize = 0;
+ let mut arguments : Vec<TD_Generic> = Vec::new();
+ match action_contents.next() {
+ None => {},
+ Some( arguments_pair ) => {
+ for arg_pair in arguments_pair.into_inner() {
+ let argument_string : String = arg_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ // ***
+ match SDParser::parse(Rule::TD_VALUE, &argument_string) {
+ Err(e) => {
+ panic!(e);
+ },
+ Ok( mut argument_as_td_val ) => {
+ match ms_specs.get(arg_count) {
+ None => {
+ return Err( HibouParsingError::UnknownMessageParameter(ms_name,arg_count) );
+ },
+ Some( (expected_type ,_) ) => {
+ let mut content = argument_as_td_val.next().unwrap();
+ let trace_action_param_td_gen : TD_Generic = parse_data(gen_ctx,content,&Some(ms_id)).unwrap();
+ let got_type = trace_action_param_td_gen.get_td_type();
+ if &got_type != expected_type {
+ return Err( HibouParsingError::WrongMessageParameterType(expected_type.clone(), got_type, ms_name, format!("{:?}", ms_specs) ) );
+ }
+ arguments.push(trace_action_param_td_gen);
+ arg_count = arg_count +1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ // ***
+ if arg_count != ms_specs.len() {
+ return Err( HibouParsingError::WrongMessageParametersNumber(ms_specs.len(), arg_count,ms_name) );
+ }
+ // ***
+ return Ok( (lf_id,act_kind,ms_id,arguments) );
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
+
+
+
diff --git a/src/from_text/interaction.rs b/src/from_text/interaction.rs
new file mode 100644
index 0000000..e1b8e06
--- /dev/null
+++ b/src/from_text/interaction.rs
@@ -0,0 +1,243 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use pest::iterators::{Pair,Pairs};
+
+
+use crate::from_text::parser::*;
+
+
+use crate::core::syntax::action::*;
+use crate::core::context::general::GeneralContext;
+use crate::core::syntax::interaction::{Interaction,ScheduleOperatorKind};
+
+use crate::from_text::error::HibouParsingError;
+use crate::from_text::action::action::{parse_emission,parse_reception};
+
+
+pub fn parse_interaction(gen_ctx : &GeneralContext, sd_interaction_pair : Pair<Rule>) -> Result<Interaction,HibouParsingError> {
+ let sd_content_pair = sd_interaction_pair.into_inner().next().unwrap();
+ match sd_content_pair.as_rule() {
+ Rule::SD_EMPTY_INTERACTION => {
+ return Ok( Interaction::Empty );
+ },
+ Rule::SD_ACTION_RECEPTION => {
+ match parse_reception(gen_ctx,&mut sd_content_pair.into_inner()) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( observable_action ) => {
+ return Ok( Interaction::Action(observable_action) );
+ }
+ }
+ },
+ Rule::SD_ACTION_EMISSION => {
+ match parse_emission(gen_ctx,&mut sd_content_pair.into_inner()) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( observable_action ) => {
+ return Ok( Interaction::Action(observable_action) );
+ }
+ }
+ },
+ Rule::SD_STRICT_INT => {
+ match get_nary_sub_interactions(gen_ctx, sd_content_pair) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut sub_ints ) => {
+ return Ok( fold_interactions_in_binary_operator(BinaryOperatorKind::Strict,&mut sub_ints) );
+ }
+ }
+ },
+ Rule::SD_SEQ_INT => {
+ match get_nary_sub_interactions(gen_ctx, sd_content_pair) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut sub_ints ) => {
+ return Ok( fold_interactions_in_binary_operator(BinaryOperatorKind::Seq,&mut sub_ints) );
+ }
+ }
+ },
+ Rule::SD_ALT_INT => {
+ match get_nary_sub_interactions(gen_ctx, sd_content_pair) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut sub_ints ) => {
+ return Ok( fold_interactions_in_binary_operator(BinaryOperatorKind::Alt,&mut sub_ints) );
+ }
+ }
+ },
+ Rule::SD_PAR_INT => {
+ match get_nary_sub_interactions(gen_ctx, sd_content_pair) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut sub_ints ) => {
+ return Ok( fold_interactions_in_binary_operator(BinaryOperatorKind::Par,&mut sub_ints) );
+ }
+ }
+ },
+ Rule::SD_LOOP_INT => {
+ let mut loop_content = sd_content_pair.into_inner();
+ let loop_kind_pair = loop_content.next().unwrap();
+ match parse_interaction(gen_ctx,loop_content.next().unwrap()) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( sub_int ) => {
+ match loop_kind_pair.as_rule() {
+ Rule::SD_LOOP_STRICT => {
+ return Ok( Interaction::Loop(ScheduleOperatorKind::Strict,Box::new(sub_int)) );
+ },
+ Rule::SD_LOOP_SEQ => {
+ return Ok( Interaction::Loop(ScheduleOperatorKind::Seq,Box::new(sub_int)) );
+ },
+ Rule::SD_LOOP_PAR => {
+ return Ok( Interaction::Loop(ScheduleOperatorKind::Par,Box::new(sub_int)) );
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+ }
+ },
+ Rule::SD_SCOPE_INT => {
+ let mut scope_content = sd_content_pair.into_inner();
+ scope_content.next(); // get rid of the operator name
+ // ***
+ let mut scoped_vr_ids : Vec<usize> = Vec::new();
+ let mut scoped_parameters = scope_content.next().unwrap().into_inner();
+ // ***
+ for scoped_var_pair in scoped_parameters {
+ let scoped_var_name : String = scoped_var_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_vr_id( &scoped_var_name ) {
+ None => {
+ return Err( HibouParsingError::MissingVariableDeclarationError( scoped_var_name ) );
+ },
+ Some( vr_id ) => {
+ scoped_vr_ids.push( vr_id );
+ }
+ }
+ }
+ // ***
+ match parse_interaction(gen_ctx,scope_content.next().unwrap()) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( parsed_sub_int ) => {
+ return Ok( Interaction::Scope( scoped_vr_ids, Box::new(parsed_sub_int) ) );
+ }
+ }
+ },/*
+ Rule::SD_CREATE_INT => {
+ let mut create_content = sd_content_pair.into_inner();
+ create_content.next(); // get rid of the operator name
+ // ***
+ let mut create_lf_ids : Vec<(usize,Option<usize>)> = Vec::new();
+ let mut create_parameters = create_content.next().unwrap().into_inner();
+ // ***
+ for create_lf_pair in create_parameters {
+ match create_lf_pair.as_rule() {
+ Rule::SD_CREATE_IN_GROUP => {
+ let mut create_in_group_contents = create_lf_pair.into_inner();
+ let create_lf_name_pair = create_in_group_contents.next().unwrap();
+ let create_lf_name : String = create_lf_name_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let create_gp_name_pair = create_in_group_contents.next().unwrap();
+ let create_gp_name : String = create_gp_name_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let lgr_id = gen_ctx.add_lf_group(create_gp_name);
+ let lf_id = gen_ctx.add_lf(create_lf_name);
+ create_lf_ids.push( (lf_id,Some(lgr_id)) );
+ },
+ Rule::SD_LIFELINE_OR_GROUP => {
+ let create_lf_name : String = create_lf_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let lf_id = gen_ctx.add_lf(create_lf_name);
+ create_lf_ids.push((lf_id,None) );
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", create_lf_pair.as_rule() );
+ }
+ }
+ }
+ // ***
+ match parse_interaction(gen_ctx,create_content.next().unwrap()) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( parsed_sub_int ) => {
+ return Ok( Interaction::Create( create_lf_ids, Box::new(parsed_sub_int) ) );
+ }
+ }
+ },*/
+ _ => {
+ panic!("what rule then ? : {:?}", sd_content_pair.as_rule());
+ }
+ }
+}
+
+fn get_nary_sub_interactions(gen_ctx : &GeneralContext, sd_content_pair : Pair<Rule>) -> Result<Vec<Interaction>,HibouParsingError> {
+ let mut strict_content = sd_content_pair.into_inner();
+ strict_content.next(); // get rid of the operator name
+ let mut sub_ints : Vec<Interaction> = Vec::new();
+ for sub_interaction in strict_content {
+ match parse_interaction(gen_ctx,sub_interaction) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( parsed_sub_int ) => {
+ sub_ints.push( parsed_sub_int );
+ }
+ }
+ }
+ return Ok( sub_ints );
+}
+
+enum BinaryOperatorKind {
+ Strict,
+ Seq,
+ Par,
+ Alt
+}
+
+fn fold_interactions_in_binary_operator(op_kind : BinaryOperatorKind, sub_ints : &mut Vec<Interaction>) -> Interaction {
+ assert!(sub_ints.len() > 0);
+ if sub_ints.len() == 1 {
+ return sub_ints.remove(0);
+ } else {
+ let first_int = sub_ints.remove(0);
+ match op_kind {
+ BinaryOperatorKind::Strict => {
+ return Interaction::Strict( Box::new(first_int), Box::new(fold_interactions_in_binary_operator(op_kind,sub_ints)));
+ },
+ BinaryOperatorKind::Seq => {
+ return Interaction::Seq( Box::new(first_int), Box::new(fold_interactions_in_binary_operator(op_kind,sub_ints)));
+ },
+ BinaryOperatorKind::Alt => {
+ return Interaction::Alt( Box::new(first_int), Box::new(fold_interactions_in_binary_operator(op_kind,sub_ints)));
+ },
+ BinaryOperatorKind::Par => {
+ return Interaction::Par( Box::new(first_int), Box::new(fold_interactions_in_binary_operator(op_kind,sub_ints)));
+ }
+ }
+ }
+}
+
+
+
+
+
diff --git a/src/from_text/mod.rs b/src/from_text/mod.rs
new file mode 100644
index 0000000..e46bf64
--- /dev/null
+++ b/src/from_text/mod.rs
@@ -0,0 +1,24 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod error;
+mod parser;
+mod data;
+mod interaction;
+mod action;
+pub mod hsf_file;
+pub mod htf_file;
+mod hibou_options;
+mod setup;
+
diff --git a/src/from_text/parser.rs b/src/from_text/parser.rs
new file mode 100644
index 0000000..021279b
--- /dev/null
+++ b/src/from_text/parser.rs
@@ -0,0 +1,24 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use pest::Parser;
+use pest::iterators::{Pair,Pairs};
+
+#[derive(Parser)]
+#[grammar = "sd_syntax.pest"]
+pub struct SDParser;
+
+
+
+
diff --git a/src/from_text/setup.rs b/src/from_text/setup.rs
new file mode 100644
index 0000000..4861f12
--- /dev/null
+++ b/src/from_text/setup.rs
@@ -0,0 +1,281 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::fs;
+use std::collections::{HashSet,HashMap};
+use std::collections::btree_map::BTreeMap;
+use std::path::Path;
+
+use pest::iterators::Pair;
+
+use crate::pest::Parser;
+
+use crate::core::syntax::interaction::Interaction;
+use crate::core::syntax::action::*;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::var_ref::VariableReference;
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::builtin::float::TD_Float;
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::string::TD_String;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::from_text::error::HibouParsingError;
+use crate::process::log::ProcessLogger;
+
+use crate::from_text::parser::*;
+use crate::from_text::data::td_type::parse_type;
+use crate::from_text::interaction::parse_interaction;
+use crate::from_text::data::generic::parse_data;
+use crate::from_text::hibou_options::{HibouOptions,parse_hibou_options};
+
+use crate::process::hibou_process::HibouPreFilter;
+use crate::from_text::hsf_file::ProcessKind;
+
+pub struct InterpretationItemPlan {
+ pub lf_id : usize,
+ pub vr_id : usize,
+ pub assignment : ValueOrNewFresh
+}
+
+pub fn parse_setup(setup_pair : Pair<Rule>,
+ gen_ctx : &mut GeneralContext,
+ file_name : &str,
+ process_kind : &ProcessKind) -> Result<(Vec<InterpretationItemPlan>,HibouOptions),HibouParsingError> {
+ // ***
+ let mut got_section_explore_options : bool = false;
+ let mut got_section_analyze_options : bool = false;
+ let mut got_section_messages : bool = false;
+ let mut got_section_variables : bool = false;
+ let mut got_section_lifelines : bool = false;
+ let mut got_section_init : bool = false;
+ // ***
+ let mut interpretation_plan : Vec<InterpretationItemPlan> = Vec::new();
+ let mut hibou_options_opt : Option<HibouOptions> = None;
+ // ***
+ let mut contents = setup_pair.into_inner();
+ while let Some(current_pair) = contents.next() {
+ match current_pair.as_rule() {
+ Rule::EXPLORE_OPTION_SECTION => {
+ if got_section_explore_options {
+ return Err( HibouParsingError::HsfSetupError("several '@explore_option' sections declared".to_string()));
+ }
+ got_section_explore_options = true;
+ match process_kind {
+ &ProcessKind::Explore => {
+ match parse_hibou_options(current_pair,file_name, process_kind) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( hoptions ) => {
+ hibou_options_opt = Some(hoptions);
+ }
+ }
+ },
+ _ => {}
+ }
+ },
+ Rule::ANALYZE_OPTION_SECTION => {
+ if got_section_analyze_options {
+ return Err( HibouParsingError::HsfSetupError("several '@analyze_option' sections declared".to_string()));
+ }
+ got_section_analyze_options = true;
+ match process_kind {
+ &ProcessKind::Analyze => {
+ match parse_hibou_options(current_pair,file_name, process_kind) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( hoptions ) => {
+ hibou_options_opt = Some(hoptions);
+ }
+ }
+ },
+ _ => {}
+ }
+ },
+ Rule::HIBOU_MODEL_MS_DECL => {
+ if got_section_messages {
+ return Err( HibouParsingError::HsfSetupError("several '@message' sections declared".to_string()));
+ }
+ got_section_messages = true;
+ parse_message_decl(current_pair,gen_ctx);
+ },
+ Rule::HIBOU_MODEL_VAR_DECL => {
+ if got_section_variables {
+ return Err( HibouParsingError::HsfSetupError("several '@variable' sections declared".to_string()));
+ }
+ got_section_variables = true;
+ parse_variable_decl(current_pair,gen_ctx);
+ },
+ Rule::HIBOU_MODEL_LF_DECL => {
+ if got_section_lifelines {
+ return Err( HibouParsingError::HsfSetupError("several '@lifeline' sections declared".to_string()));
+ }
+ got_section_lifelines = true;
+ parse_lifeline_decl(current_pair,gen_ctx);
+ },
+ Rule::HIBOU_MODEL_VAR_INIT => {
+ if got_section_init {
+ return Err( HibouParsingError::HsfSetupError("several '@init' sections declared".to_string()));
+ }
+ got_section_init = true;
+ match parse_initialization(current_pair,gen_ctx) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( iip ) => {
+ interpretation_plan = iip;
+ }
+ }
+ },
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+ match hibou_options_opt {
+ None => {
+ match process_kind {
+ ProcessKind::Analyze => {
+ return Ok( (interpretation_plan,HibouOptions::default_analyze()) );
+ },
+ _ => {
+ return Ok( (interpretation_plan,HibouOptions::default_explore()) );
+ }
+ }
+ },
+ Some(hibou_options) => {
+ return Ok( (interpretation_plan,hibou_options) );
+ }
+ }
+}
+
+fn parse_message_decl(ms_decl_pair : Pair<Rule>, gen_ctx : &mut GeneralContext) -> Result<(),HibouParsingError> {
+ for msg_decl_pair in ms_decl_pair.into_inner() {
+ let mut msg_decl_content = msg_decl_pair.into_inner();
+ let ms_name : String = msg_decl_content.next().unwrap().as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let mut ms_spec : Vec<(TD_DataType,Option<String>)> = Vec::new();
+ match msg_decl_content.next() {
+ None => {},
+ Some( msg_pr_decl ) => {
+ for pr_decl_pair in msg_pr_decl.into_inner() {
+ match pr_decl_pair.as_rule() {
+ Rule::PRM_DECLARATION => {
+ let mut var_decl_content = pr_decl_pair.into_inner();
+ let vr_name : String = var_decl_content.next().unwrap().as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let td_type_pair = var_decl_content.next().unwrap();
+ let (td_type, is_clock) = parse_type(td_type_pair);
+ if is_clock {
+ panic!("message parameter argument cannot be a clock");
+ }
+ ms_spec.push( (td_type,Some(vr_name)) );
+ },
+ _ => {
+ let (td_type, is_clock) = parse_type(pr_decl_pair);
+ if is_clock {
+ panic!("message parameter argument cannot be a clock");
+ }
+ ms_spec.push( (td_type,None) );
+ }
+ }
+ }
+ }
+ }
+ gen_ctx.add_msg(ms_name,ms_spec);
+ }
+ return Ok(());
+}
+
+fn parse_variable_decl(vr_decl_pair : Pair<Rule>, gen_ctx : &mut GeneralContext ) {
+ for var_decl_pair in vr_decl_pair.into_inner() {
+ let mut var_decl_content = var_decl_pair.into_inner();
+ let vr_name : String = var_decl_content.next().unwrap().as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ let td_type_pair = var_decl_content.next().unwrap();
+ let (td_type, is_clock) = parse_type(td_type_pair);
+ let new_vr_id = gen_ctx.get_vr_num();
+ gen_ctx.add_vr( vr_name.clone(), td_type);
+ if is_clock {
+ gen_ctx.add_as_clock( new_vr_id );
+ }
+ }
+}
+
+fn parse_lifeline_decl(lf_decl_pair : Pair<Rule>, gen_ctx : &mut GeneralContext ) {
+ for lf_pair in lf_decl_pair.into_inner() {
+ let lf_name : String = lf_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ gen_ctx.add_lf(lf_name);
+ }
+}
+
+fn parse_initialization(init_pair : Pair<Rule>, gen_ctx : &GeneralContext ) -> Result<Vec<InterpretationItemPlan>, HibouParsingError> {
+ let mut interpretation_plan : Vec<InterpretationItemPlan> = Vec::new();
+ for var_init_pair in init_pair.into_inner() {
+ let mut var_init_contents = var_init_pair.into_inner();
+ // ***
+ let lf_id : usize;
+ {
+ let lf_name_pair = var_init_contents.next().unwrap();
+ let lf_name : String = lf_name_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_lf_id( &lf_name) {
+ None => {
+ return Err( HibouParsingError::MissingLifelineDeclarationError(lf_name) );
+ },
+ Some( got_lf_id ) => {
+ lf_id = got_lf_id;
+ }
+ }
+ }
+ // ***
+ let vr_id : usize;
+ {
+ let vr_name_pair = var_init_contents.next().unwrap();
+ let vr_name : String = vr_name_pair.as_str().chars().filter(|c| !c.is_whitespace()).collect();
+ match gen_ctx.get_vr_id( &vr_name) {
+ None => {
+ return Err( HibouParsingError::MissingVariableDeclarationError(vr_name) );
+ },
+ Some( got_vr_id ) => {
+ vr_id = got_vr_id;
+ }
+ }
+ }
+ // ***
+ {
+ let assignment_pair = var_init_contents.next().unwrap();
+ match assignment_pair.as_rule() {
+ Rule::TD_VALUE => {
+ match parse_data(gen_ctx,assignment_pair,&None) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( td_generic ) => {
+ interpretation_plan.push( InterpretationItemPlan{lf_id,vr_id,assignment:ValueOrNewFresh::Value(td_generic)});
+ }
+ }
+ },
+ Rule::NEW_FRESH => {
+ interpretation_plan.push( InterpretationItemPlan{lf_id,vr_id,assignment:ValueOrNewFresh::NewFresh});
+ },
+ _ => {
+ panic!("what rule then ? : {:?}", assignment_pair.as_rule() );
+ }
+ }
+ }
+ // ***
+ }
+ return Ok(interpretation_plan);
+}
\ No newline at end of file
diff --git a/src/grpc_connect/calls.rs b/src/grpc_connect/calls.rs
new file mode 100644
index 0000000..86eca58
--- /dev/null
+++ b/src/grpc_connect/calls.rs
@@ -0,0 +1,159 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+use crate::diversity::symbex_client::SymbexClient;
+use crate::diversity::model_definition_request::ModelAlt;
+use crate::diversity::*;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::core::syntax::action::*;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::grpc_connect::to_grpc::{td_generic_to_grpc,td_bool_to_grpc};
+use crate::grpc_connect::from_grpc::expression_from_grpc;
+use crate::grpc_connect::xlia_reference_name_tools::{action_diversity_fqn,variable_diversity_fqn,open_scopes_action_diversity_fqn};
+
+
+
+
+pub async fn symbex_open_scopes(client : &mut SymbexClient<tonic::transport::Channel>, gen_ctx : &GeneralContext, exe_ctx : &mut ExecutionContext, initial_diversity_ec_id : u32) -> u32 {
+ let mut current_diversity_ec_id : u32 = initial_diversity_ec_id;
+ for lf_id in 0..gen_ctx.get_lf_num() {
+ let open_scopes_action_fqn = open_scopes_action_diversity_fqn(gen_ctx,lf_id);
+ let eval_machine_request = SymbexEvalRunnableRequest {
+ execution_context_id: current_diversity_ec_id,
+ runnable_element_id: open_scopes_action_fqn,
+ variable_value: Vec::new()
+ };
+ println!("EVAL MACHINE REQUEST for OPEN SCOPE on lf {} = {:?}",lf_id, eval_machine_request);
+ let eval_machine_response = client.symbex_eval_basic_machine(tonic::Request::new(eval_machine_request)).await.unwrap();
+ let eval_machine_reply : SymbexEvalRunnableBasicReply = eval_machine_response.into_inner();
+ println!("EVAL MACHINE RESPONSE = {:?}", eval_machine_reply);
+ current_diversity_ec_id = eval_machine_reply.execution_context_id;
+ // ***
+ for symbol_creation_report in &eval_machine_reply.created_symbols {
+ let symbol_fqn = &symbol_creation_report.symbol_id;
+ let symbol_type = TD_DataType::from_grpc(symbol_creation_report.r#type);
+ println!("DIVERSITY created the symbol '{:?}' of type '{:?}'...", symbol_fqn, symbol_type);
+ let new_symbol_id = exe_ctx.add_diversity_symbol(symbol_fqn,&symbol_type);
+ println!("...kept track of in HIBOU context as #{}", new_symbol_id);
+ }
+ }
+ return current_diversity_ec_id;
+}
+
+
+pub enum SymbexResult {
+ Success(SymbexResultSuccess),
+ UnSAT
+}
+
+pub struct SymbexResultSuccess {
+ pub new_diversity_ec_id : u32,
+ pub firing_condition : TD_Bool
+}
+
+/**
+- action_name : &String
+ name of the action to fire in the xlia model
+ it corresponds to the position of the parent action within the initial model
+- ec_id : u32
+ identifier of the execution context
+- variables_to_update : Vec<(String,TD_Generic)>
+ list of variables to update in the xlia model
+ + first arg is the full identifier of the variable
+ + second arg is the term which aims to replace it
+**/
+pub async fn symbex_fire_action( gen_ctx : &GeneralContext,
+ exe_ctx : &mut ExecutionContext,
+ diversity_ec_id : u32,
+ client : &mut SymbexClient<tonic::transport::Channel>,
+ target_action_fqn : String,
+ variables_to_update : Vec<VariableValuePair>)
+ -> SymbexResult {
+
+ let eval_machine_request = SymbexEvalRunnableRequest {
+ execution_context_id: diversity_ec_id.into(),
+ runnable_element_id: target_action_fqn.into(),
+ variable_value: variables_to_update
+ };
+ println!("EVAL MACHINE REQUEST = {:?}", eval_machine_request);
+
+ let eval_machine_response = client.symbex_eval_basic_machine(tonic::Request::new(eval_machine_request)).await.unwrap();
+ let eval_machine_reply : SymbexEvalRunnableBasicReply = eval_machine_response.into_inner();
+ println!("EVAL MACHINE REPLY = {:?}", eval_machine_reply);
+
+ if eval_machine_reply.is_satisfiable {
+ // ***
+ let new_diversity_ec_id : u32 = eval_machine_reply.execution_context_id;
+ // ***
+ for symbol_creation_report in eval_machine_reply.created_symbols {
+ let symbol_fqn : String = symbol_creation_report.symbol_id;
+ let symbol_type = TD_DataType::from_grpc(symbol_creation_report.r#type);
+ println!("DIVERSITY created the symbol '{:?}' of type '{:?}'...", symbol_fqn, symbol_type);
+ let new_symbol_id = exe_ctx.add_diversity_symbol(&symbol_fqn,&symbol_type);
+ println!("...kept track of in HIBOU context as #{}", new_symbol_id);
+ }
+ // ***
+ let path_condition_expr = eval_machine_reply.path_condition.unwrap();
+ let pc_td_gen = expression_from_grpc(gen_ctx,exe_ctx,&path_condition_expr, &TD_DataType::Bool).unwrap();
+ let path_condition : TD_Bool = pc_td_gen.as_td_bool();
+ println!("DIVERSITY provided the path condition '{:?}'\nin the new context {:?}...", &path_condition,&new_diversity_ec_id);
+ exe_ctx.set_path_condition(path_condition);
+ println!("...updated in HIBOU context");
+ // ***
+ let firing_condition_expr = eval_machine_reply.other_condition.unwrap();
+ let fc_td_gen = expression_from_grpc(gen_ctx,exe_ctx,&firing_condition_expr, &TD_DataType::Bool).unwrap();
+ let firing_condition : TD_Bool = fc_td_gen.as_td_bool();
+ // ***
+ let symbex_success = SymbexResultSuccess{new_diversity_ec_id,firing_condition};
+ return SymbexResult::Success(symbex_success);
+ } else {
+ return SymbexResult::UnSAT;
+ }
+}
+
+
+pub async fn symbex_request_variable( gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ diversity_ec_id : u32,
+ client : &mut SymbexClient<tonic::transport::Channel>,
+ var_fqn : String,
+ var_expected_type : &TD_DataType) -> TD_Generic {
+
+ // ***
+ let query_value_request = tonic::Request::new(QueryValueForVariableRequest {
+ execution_context_id: diversity_ec_id.into(),
+ variable_id:vec![var_fqn]
+ });
+ println!("QUERY VALUE REQUEST = {:?}", query_value_request);
+
+ let query_value_response = client.query_valueof_variable(query_value_request).await.unwrap();
+ let query_value_reply : QueryValueForVariableReply = query_value_response.into_inner();
+ println!("QUERY VALUE REPLY = {:?}", query_value_reply);
+
+ let var_value_pair : &VariableValuePair = query_value_reply.variable_value.get(0).unwrap();
+ match &var_value_pair.value {
+ None => {
+ panic!();
+ },
+ Some(ref grpc_expression) => {
+ return expression_from_grpc(gen_ctx,exe_ctx,&grpc_expression,var_expected_type).unwrap();
+ }
+ }
+}
diff --git a/src/grpc_connect/from_grpc.rs b/src/grpc_connect/from_grpc.rs
new file mode 100644
index 0000000..3035bf2
--- /dev/null
+++ b/src/grpc_connect/from_grpc.rs
@@ -0,0 +1,593 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::core::syntax::data::var_ref::VariableReference;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::builtin::bool::*;
+use crate::core::syntax::data::builtin::number::*;
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::float::TD_Float;
+use crate::core::syntax::data::builtin::string::TD_String;
+
+use crate::diversity::*;
+use crate::diversity::expression::ExpressionAlt;
+
+use crate::core::error::HibouCoreError;
+
+
+fn symbol_reference_from_grpc(gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ symbol_fqn : &String,
+ expected_type : &TD_DataType) -> Result<TD_Generic,HibouCoreError> {
+ match exe_ctx.get_sy_type_from_fqn( &symbol_fqn) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( sy_type ) => {
+ if &sy_type != expected_type {
+ return Err( HibouCoreError::WronglyTypedGrpcInput(symbol_fqn.clone(), sy_type.clone(), expected_type.as_xlia_str() ));
+ }
+ match sy_type {
+ TD_DataType::String => {
+ let td_str = TD_String::Reference( VariableReference::SYMBOL( exe_ctx.get_sy_id_from_fqn(&symbol_fqn).unwrap() ) );
+ return Ok( TD_Generic::String(td_str) );
+ },
+ TD_DataType::Integer => {
+ let td_int = TD_Integer::Reference( VariableReference::SYMBOL( exe_ctx.get_sy_id_from_fqn(&symbol_fqn).unwrap() ) );
+ return Ok( TD_Generic::Integer(td_int) );
+ },
+ TD_DataType::Float => {
+ let td_float = TD_Float::Reference( VariableReference::SYMBOL( exe_ctx.get_sy_id_from_fqn(&symbol_fqn).unwrap() ) );
+ return Ok( TD_Generic::Float(td_float) );
+ },
+ TD_DataType::Bool => {
+ let td_bool = TD_Bool::Reference( VariableReference::SYMBOL( exe_ctx.get_sy_id_from_fqn(&symbol_fqn).unwrap() ) );
+ return Ok( TD_Generic::Bool(td_bool) );
+ }
+ }
+ }
+ }
+}
+
+fn get_sub_expressions(gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ operation : &Operation,
+ expected_type : &TD_DataType) -> Result<Vec< TD_Generic >,HibouCoreError> {
+ let mut sub_expressions : Vec< TD_Generic > = Vec::new();
+ for expression in &operation.operand {
+ match expression_from_grpc(gen_ctx,exe_ctx,expression,expected_type) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( td_gen ) => {
+ sub_expressions.push( td_gen );
+ }
+ }
+ }
+ return Ok( sub_expressions );
+}
+
+fn operation_from_grpc(gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ operation : &Operation,
+ expected_type : &TD_DataType) -> Result<TD_Generic,HibouCoreError> {
+ if operation.operator_kind == ( OperatorKind::Add as i32 ) {
+ match get_sub_expressions(gen_ctx,exe_ctx,operation,expected_type) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut sub_expressions ) => {
+ match expected_type {
+ TD_DataType::Integer => {
+ let mut add_vec : Vec<(ARITH_ADD_SIGN,TD_Integer)> = Vec::new();
+ for sub_expr in sub_expressions {
+ match sub_expr {
+ TD_Generic::Integer(td_int) => {
+ add_vec.push( (ARITH_ADD_SIGN::Plus, td_int) );
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }
+ }
+ return Ok( TD_Generic::Integer( TD_Integer::Add(add_vec) ) );
+ },
+ TD_DataType::Float => {
+ let mut add_vec : Vec<(ARITH_ADD_SIGN,TD_Float)> = Vec::new();
+ for sub_expr in sub_expressions {
+ match sub_expr {
+ TD_Generic::Float(td_float) => {
+ add_vec.push( (ARITH_ADD_SIGN::Plus, td_float) );
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }
+ }
+ return Ok( TD_Generic::Float( TD_Float::Add(add_vec) ) );
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }
+ }
+ }
+ } else if operation.operator_kind == ( OperatorKind::Minus as i32 ) {
+ match get_sub_expressions(gen_ctx,exe_ctx,operation,expected_type) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut sub_expressions ) => {
+ match expected_type {
+ TD_DataType::Integer => {
+ let mut add_vec : Vec<(ARITH_ADD_SIGN,TD_Integer)> = Vec::new();
+ let mut first : bool = true;
+ for sub_expr in sub_expressions {
+ match sub_expr {
+ TD_Generic::Integer(td_int) => {
+ if first {
+ add_vec.push( (ARITH_ADD_SIGN::Plus, td_int) );
+ first = false;
+ } else {
+ add_vec.push( (ARITH_ADD_SIGN::Minus, td_int) );
+ }
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }
+ }
+ return Ok( TD_Generic::Integer( TD_Integer::Add(add_vec) ) );
+ },
+ TD_DataType::Float => {
+ let mut add_vec : Vec<(ARITH_ADD_SIGN,TD_Float)> = Vec::new();
+ let mut first : bool = true;
+ for sub_expr in sub_expressions {
+ match sub_expr {
+ TD_Generic::Float(td_float) => {
+ if first {
+ add_vec.push( (ARITH_ADD_SIGN::Plus, td_float) );
+ first = false;
+ } else {
+ add_vec.push( (ARITH_ADD_SIGN::Minus, td_float) );
+ }
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }
+ }
+ return Ok( TD_Generic::Float( TD_Float::Add(add_vec) ) );
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }}}
+ } else if operation.operator_kind == ( OperatorKind::Uminus as i32 ) {
+ match get_sub_expressions(gen_ctx,exe_ctx,operation,expected_type) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut sub_expressions ) => {
+ match expected_type {
+ TD_DataType::Integer => {
+ if sub_expressions.len() != 1 {
+ return Err(HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()));
+ } else {
+ let td_gen = sub_expressions.remove(0);
+ match td_gen {
+ TD_Generic::Integer(td_int) => {
+ return Ok(TD_Generic::Integer(TD_Integer::Minus(Box::new(td_int))));
+ },
+ _ => {
+ return Err(HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()));
+ }
+ }
+ }
+ },
+ TD_DataType::Float => {
+ if sub_expressions.len() != 1 {
+ return Err(HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()));
+ } else {
+ let td_gen = sub_expressions.remove(0);
+ match td_gen {
+ TD_Generic::Float(td_float) => {
+ return Ok(TD_Generic::Float(TD_Float::Minus(Box::new(td_float))));
+ },
+ _ => {
+ return Err(HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()));
+ }
+ }
+ }
+ },
+ _ => {
+ return Err(HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()));
+ }
+ }
+ }}
+ } else if operation.operator_kind == ( OperatorKind::Mult as i32 ) {
+ match get_sub_expressions(gen_ctx,exe_ctx,operation,expected_type) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut sub_expressions ) => {
+ match expected_type {
+ TD_DataType::Integer => {
+ let mut factor_vec : Vec<(ARITH_FACTOR_SIGN,TD_Integer)> = Vec::new();
+ for sub_expr in sub_expressions {
+ match sub_expr {
+ TD_Generic::Integer(td_int) => {
+ factor_vec.push( (ARITH_FACTOR_SIGN::Mult, td_int) );
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }
+ }
+ return Ok( TD_Generic::Integer( TD_Integer::Factor(factor_vec) ) );
+ },
+ TD_DataType::Float => {
+ let mut factor_vec : Vec<(ARITH_FACTOR_SIGN,TD_Float)> = Vec::new();
+ for sub_expr in sub_expressions {
+ match sub_expr {
+ TD_Generic::Float(td_float) => {
+ factor_vec.push( (ARITH_FACTOR_SIGN::Mult, td_float) );
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }
+ }
+ return Ok( TD_Generic::Float( TD_Float::Factor(factor_vec) ) );
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }}}
+ } else if operation.operator_kind == ( OperatorKind::Div as i32 ) {
+ match get_sub_expressions(gen_ctx,exe_ctx,operation,expected_type) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut sub_expressions ) => {
+ match expected_type {
+ TD_DataType::Integer => {
+ let mut factor_vec : Vec<(ARITH_FACTOR_SIGN,TD_Integer)> = Vec::new();
+ let mut first : bool = true;
+ for sub_expr in sub_expressions {
+ match sub_expr {
+ TD_Generic::Integer(td_int) => {
+ if first {
+ factor_vec.push( (ARITH_FACTOR_SIGN::Mult, td_int) );
+ first = false;
+ } else {
+ factor_vec.push( (ARITH_FACTOR_SIGN::Div, td_int) );
+ }
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }
+ }
+ return Ok( TD_Generic::Integer( TD_Integer::Factor(factor_vec) ) );
+ },
+ TD_DataType::Float => {
+ let mut factor_vec : Vec<(ARITH_FACTOR_SIGN,TD_Float)> = Vec::new();
+ let mut first : bool = true;
+ for sub_expr in sub_expressions {
+ match sub_expr {
+ TD_Generic::Float(td_float) => {
+ if first {
+ factor_vec.push( (ARITH_FACTOR_SIGN::Mult, td_float) );
+ first = false;
+ } else {
+ factor_vec.push( (ARITH_FACTOR_SIGN::Div, td_float) );
+ }
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }
+ }
+ return Ok( TD_Generic::Float( TD_Float::Factor(factor_vec) ) );
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }}}
+ } else if operation.operator_kind == ( OperatorKind::Or as i32 ) {
+ match get_sub_expressions(gen_ctx,exe_ctx,operation,expected_type) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut sub_expressions ) => {
+ match expected_type {
+ TD_DataType::Bool => {
+ let mut sub_bool_vec : Vec<TD_Bool> = Vec::new();
+ for sub_expr in sub_expressions {
+ match sub_expr {
+ TD_Generic::Bool(td_bool) => {
+ sub_bool_vec.push(td_bool);
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }
+ }
+ return Ok( TD_Generic::Bool( TD_Bool::OR(sub_bool_vec) ) );
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }}}
+ } else if operation.operator_kind == ( OperatorKind::And as i32 ) {
+ match get_sub_expressions(gen_ctx,exe_ctx,operation,expected_type) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut sub_expressions ) => {
+ match expected_type {
+ TD_DataType::Bool => {
+ let mut sub_bool_vec : Vec<TD_Bool> = Vec::new();
+ for sub_expr in sub_expressions {
+ match sub_expr {
+ TD_Generic::Bool(td_bool) => {
+ sub_bool_vec.push(td_bool);
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }
+ }
+ return Ok( TD_Generic::Bool( TD_Bool::AND(sub_bool_vec) ) );
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }}}
+ } else if operation.operator_kind == ( OperatorKind::Not as i32 ) {
+ match get_sub_expressions(gen_ctx,exe_ctx,operation,expected_type) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( mut sub_expressions ) => {
+ match expected_type {
+ TD_DataType::Bool => {
+ if sub_expressions.len() != 1 {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ } else {
+ let sub_expr = sub_expressions.remove(0);
+ match sub_expr {
+ TD_Generic::Bool(td_bool) => {
+ return Ok( TD_Generic::Bool( TD_Bool::NOT(Box::new(td_bool)) ) );
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }
+ }
+ },
+ _ => {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ }
+ }}}
+ } else if operation.operator_kind == ( OperatorKind::Eq as i32 ) {
+ if operation.operand.len() != 2 || expected_type != &TD_DataType::Bool {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ } else {
+ match get_branches_of_comparaison_operator(gen_ctx,exe_ctx,operation) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (got_type,mut sub_expressions) ) => {
+ let first = sub_expressions.remove(0);
+ let second = sub_expressions.remove(0);
+ let td_bool = TD_Bool::COMPARE(Bool_Compare::Equal, Box::new(first), Box::new(second));
+ return Ok( TD_Generic::Bool( td_bool ) );
+ }
+ }
+ }
+ } else if operation.operator_kind == ( OperatorKind::Neq as i32 ) {
+ if operation.operand.len() != 2 || expected_type != &TD_DataType::Bool {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ } else {
+ match get_branches_of_comparaison_operator(gen_ctx,exe_ctx,operation) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (got_type,mut sub_expressions) ) => {
+ let first = sub_expressions.remove(0);
+ let second = sub_expressions.remove(0);
+ let td_bool = TD_Bool::COMPARE(Bool_Compare::Different, Box::new(first), Box::new(second));
+ return Ok( TD_Generic::Bool( td_bool ) );
+ }
+ }
+ }
+ } else if operation.operator_kind == ( OperatorKind::Gt as i32 ) {
+ if operation.operand.len() != 2 || expected_type != &TD_DataType::Bool {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ } else {
+ match get_branches_of_comparaison_operator(gen_ctx,exe_ctx,operation) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (got_type,mut sub_expressions) ) => {
+ let first = sub_expressions.remove(0);
+ let second = sub_expressions.remove(0);
+ let td_bool = TD_Bool::COMPARE(Bool_Compare::Greater, Box::new(first), Box::new(second));
+ return Ok( TD_Generic::Bool( td_bool ) );
+ }
+ }
+ }
+ } else if operation.operator_kind == ( OperatorKind::Gte as i32 ) {
+ if operation.operand.len() != 2 || expected_type != &TD_DataType::Bool {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ } else {
+ match get_branches_of_comparaison_operator(gen_ctx,exe_ctx,operation) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (got_type,mut sub_expressions) ) => {
+ let first = sub_expressions.remove(0);
+ let second = sub_expressions.remove(0);
+ let td_bool = TD_Bool::COMPARE(Bool_Compare::GreaterOrEqual, Box::new(first), Box::new(second));
+ return Ok( TD_Generic::Bool( td_bool ) );
+ }
+ }
+ }
+ } else if operation.operator_kind == ( OperatorKind::Lt as i32 ) {
+ if operation.operand.len() != 2 || expected_type != &TD_DataType::Bool {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ } else {
+ match get_branches_of_comparaison_operator(gen_ctx,exe_ctx,operation) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (got_type,mut sub_expressions) ) => {
+ let first = sub_expressions.remove(0);
+ let second = sub_expressions.remove(0);
+ let td_bool = TD_Bool::COMPARE(Bool_Compare::Lower, Box::new(first), Box::new(second));
+ return Ok( TD_Generic::Bool( td_bool ) );
+ }
+ }
+ }
+ } else if operation.operator_kind == ( OperatorKind::Lte as i32 ) {
+ if operation.operand.len() != 2 || expected_type != &TD_DataType::Bool {
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) );
+ } else {
+ match get_branches_of_comparaison_operator(gen_ctx,exe_ctx,operation) {
+ Err(e) => {
+ return Err(e);
+ },
+ Ok( (got_type,mut sub_expressions) ) => {
+ let first = sub_expressions.remove(0);
+ let second = sub_expressions.remove(0);
+ let td_bool = TD_Bool::COMPARE(Bool_Compare::LowerOrEqual, Box::new(first), Box::new(second));
+ return Ok( TD_Generic::Bool( td_bool ) );
+ }
+ }
+ }
+ } else {
+ return Err( HibouCoreError::UnknownOperatorInGrpcInputOperation(operation.clone()) );
+ }
+}
+
+fn get_branches_of_comparaison_operator(gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ operation : &Operation) -> Result<(TD_DataType,Vec< TD_Generic >),HibouCoreError> {
+
+ match get_sub_expressions(gen_ctx,exe_ctx,operation,&TD_DataType::String) {
+ Err(e) => {}
+ Ok( sub_expressions ) => {
+ return Ok( (TD_DataType::String, sub_expressions) );
+ }
+ }
+
+ match get_sub_expressions(gen_ctx,exe_ctx,operation,&TD_DataType::Bool) {
+ Err(e) => {}
+ Ok( sub_expressions ) => {
+ return Ok( (TD_DataType::Bool, sub_expressions) );
+ }
+ }
+
+ match get_sub_expressions(gen_ctx,exe_ctx,operation,&TD_DataType::Integer) {
+ Err(e) => {}
+ Ok( sub_expressions ) => {
+ return Ok( (TD_DataType::Integer, sub_expressions) );
+ }
+ }
+
+ match get_sub_expressions(gen_ctx,exe_ctx,operation,&TD_DataType::Float) {
+ Err(e) => {}
+ Ok( sub_expressions ) => {
+ return Ok( (TD_DataType::Float, sub_expressions) );
+ }
+ }
+
+ return Err( HibouCoreError::WronglyTypedGrpcInputOperation(operation.clone()) )
+}
+
+
+
+pub fn expression_from_grpc(gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ expression : &Expression,
+ expected_type : &TD_DataType ) -> Result<TD_Generic,HibouCoreError> {
+ match &expression.expression_alt {
+ None => {
+ panic!("forbidden empty expression");
+ },
+ Some( expression_alt ) => {
+ match expression_alt {
+ ExpressionAlt::SymbolId( symbol_fqn ) => {
+ return symbol_reference_from_grpc(gen_ctx,exe_ctx,symbol_fqn,expected_type);
+ },
+ ExpressionAlt::VariableId( variable_fqn ) => {
+ //DIVERSITY should only return terms of symbols; no variables should appear in those terms
+ panic!();
+ //return variable_reference_from_grpc(gen_ctx,exe_ctx,var_id);
+ },
+ ExpressionAlt::Operation( sub_operation ) => {
+ return operation_from_grpc(gen_ctx,exe_ctx,sub_operation,expected_type);
+ },
+ ExpressionAlt::RawString( raw_string ) => {
+ if expected_type == &TD_DataType::String {
+ return Ok( TD_Generic::String(TD_String::Value(raw_string.clone())) );
+ } else {
+ return Err( HibouCoreError::WronglyTypedGrpcInput(raw_string.clone(), expected_type.clone(), TD_DataType::String.as_xlia_str() ) );
+ }
+ },
+ ExpressionAlt::RawInteger( raw_int ) => {
+ if expected_type == &TD_DataType::Integer {
+ return Ok( TD_Generic::Integer(TD_Integer::Value( *raw_int as i64 )) );
+ } else if expected_type == &TD_DataType::Float {
+ return Ok( TD_Generic::Float(TD_Float::Value( *raw_int as f64 )) );
+ } else {
+ return Err( HibouCoreError::WronglyTypedGrpcInput(raw_int.to_string(), expected_type.clone(), format!("{} or {}",TD_DataType::Integer.as_xlia_str(),TD_DataType::Float.as_xlia_str()) ) );
+ }
+ },
+ ExpressionAlt::RawFloat( raw_float ) => {
+ if expected_type == &TD_DataType::Integer {
+ if (*raw_float).fract() != 0.0 {
+ return Err( HibouCoreError::WronglyTypedGrpcInput(raw_float.to_string(), expected_type.clone(), format!("{} or {}",TD_DataType::Integer.as_xlia_str(),TD_DataType::Float.as_xlia_str()) ) );
+ } else {
+ return Ok( TD_Generic::Integer(TD_Integer::Value( *raw_float as i64 )) );
+ }
+ } else if expected_type == &TD_DataType::Float {
+ return Ok( TD_Generic::Float(TD_Float::Value( *raw_float as f64 )) );
+ } else {
+ return Err( HibouCoreError::WronglyTypedGrpcInput(raw_float.to_string(), expected_type.clone(), format!("{} or {}",TD_DataType::Integer.as_xlia_str(),TD_DataType::Float.as_xlia_str()) ) );
+ }
+ },
+ ExpressionAlt::RawBool( raw_bool ) => {
+ if expected_type == &TD_DataType::Bool {
+ let td_gen : TD_Generic;
+ if *raw_bool {
+ td_gen = TD_Generic::Bool(TD_Bool::TRUE);
+ } else {
+ td_gen = TD_Generic::Bool(TD_Bool::FALSE);
+ }
+ return Ok( td_gen );
+ } else {
+ return Err( HibouCoreError::WronglyTypedGrpcInput(raw_bool.to_string(), expected_type.clone(), TD_DataType::Bool.as_xlia_str() ) );
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/grpc_connect/init_calls.rs b/src/grpc_connect/init_calls.rs
new file mode 100644
index 0000000..5c4f573
--- /dev/null
+++ b/src/grpc_connect/init_calls.rs
@@ -0,0 +1,134 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashSet;
+use std::collections::btree_map::BTreeMap;
+
+use crate::diversity::symbex_client::SymbexClient;
+use crate::diversity::model_definition_request::ModelAlt;
+use crate::diversity::*;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::core::syntax::action::*;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::grpc_connect::to_grpc::{td_generic_to_grpc,td_bool_to_grpc};
+use crate::grpc_connect::from_grpc::expression_from_grpc;
+
+use crate::grpc_connect::xlia_reference_name_tools::*;
+use crate::grpc_connect::calls::*;
+
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+
+pub async fn symbex_init_model(gen_ctx : &GeneralContext, exe_ctx : &mut ExecutionContext, model_text : String) -> (SymbexClient<tonic::transport::Channel>,u32) {
+
+ let mut client = SymbexClient::connect("http://[::1]:50051").await.unwrap();
+ // INITIALIZATION
+ let initialization_request = tonic::Request::new(InitializationRequest {
+ session_id: "hibou_main".into(),
+ });
+ println!("INITIALIZATION REQUEST = {:?}", initialization_request);
+ let initialization_response = client.initialization(initialization_request).await.unwrap();
+ let initialization_reply = initialization_response.into_inner();
+ println!("INITIALIZATION REPLY = {:?}", initialization_reply);
+ // ***
+
+ // XLIA MODEL PARSING
+ let model_parse_request = tonic::Request::new(ModelDefinitionRequest {
+ model_alt: Some( ModelAlt::ModelRawText(model_text) ),
+ workflow_alt : None
+ });
+ println!("MODEL PARSE REQUEST = {:?}", model_parse_request);
+ let model_parse_response = client.model_parse_text(model_parse_request).await.unwrap();
+ let model_parse_reply = model_parse_response.into_inner();
+ println!("MODEL PARSE REPLY = {:?}", model_parse_reply);
+ // ***
+
+ // EVAL INIT
+ let eval_init_request = tonic::Request::new(SymbexEvalInitRequest {
+ variable_value: Vec::new(),
+ });
+ println!("EVAL INIT REQUEST = {:?}", eval_init_request);
+ let eval_init_response = client.symbex_eval_init(eval_init_request).await.unwrap();
+ let eval_init_reply = eval_init_response.into_inner();
+ println!("EVAL INIT REPLY = {:?}", eval_init_reply );
+ // ***
+ // open scopes called once at the beginning so that every variable vector in the DIVERSITY model has exactly one place for the original instance of the HIBOU meta-variable
+ let current_diversity_ec_id = symbex_open_scopes(&mut client, gen_ctx, exe_ctx,eval_init_reply.execution_context_id).await;
+ // ***
+ return (client,current_diversity_ec_id);
+}
+
+pub async fn symbex_fire_lifeline_initializations(client : &mut SymbexClient<tonic::transport::Channel>,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &mut ExecutionContext,
+ initial_div_ec_id : u32) -> u32 {
+ let mut div_ec_id = initial_div_ec_id;
+ for lf_id in 0..gen_ctx.get_lf_num() {
+ let lf_name = gen_ctx.get_lf_name(lf_id).unwrap();
+ let initialization_action_fqn = format!("{}.initialization",lf_name);
+ // ***
+ let mut lf_interpretation : BTreeMap<usize,TD_Generic>;
+ match exe_ctx.get_lf_interpretation(lf_id) {
+ None => {
+ lf_interpretation = BTreeMap::new();
+ },
+ Some( got_lfint ) => {
+ lf_interpretation = got_lfint.clone();
+ }
+ }
+ // ***
+ let appearing_variables : Vec<usize> = lf_interpretation.iter().map(|(k,v)| *k).collect();
+ // ***
+ let mut indexes_of_variables_in_diversity : Vec<VariableValuePair> = Vec::new();
+ for vr_id in &appearing_variables {
+ let (_,meta_var_idx) = exe_ctx.get_vr_parent_name_and_child_id(gen_ctx,*vr_id).unwrap();
+ let varindex_fqn = varindex_diversity_fqn(gen_ctx,exe_ctx, lf_id,*vr_id);
+ let td_gen = TD_Generic::Integer(TD_Integer::Value(meta_var_idx as i64));
+ indexes_of_variables_in_diversity.push( VariableValuePair{variable_id:varindex_fqn,
+ value : Some(td_generic_to_grpc(gen_ctx,exe_ctx,lf_id,&td_gen))} );
+ }
+ // ***
+ println!("firing initialization for lifeline {}",lf_name);
+ match symbex_fire_action(&gen_ctx,
+ exe_ctx,
+ div_ec_id,
+ client,
+ initialization_action_fqn,
+ indexes_of_variables_in_diversity).await {
+ SymbexResult::Success(success) => {
+ div_ec_id = success.new_diversity_ec_id;
+ // ***
+ for vr_id in &appearing_variables {
+ let vr_type = exe_ctx.get_vr_type(gen_ctx,*vr_id).unwrap();
+ let var_fqn = variable_diversity_fqn(gen_ctx,exe_ctx,lf_id,*vr_id);
+ println!("HIBOU requested value of variable '{:?}' to DIVERSITY...",var_fqn);
+ let td_gen = symbex_request_variable(gen_ctx,exe_ctx,div_ec_id,client,var_fqn,&vr_type).await;
+ println!("...DIVERSITY provided value '{:?}'...",td_gen);
+ lf_interpretation.insert(*vr_id,td_gen);
+ println!("...updated in HIBOU intrepretation");
+ }
+ // ***
+ exe_ctx.set_lf_interpretation(lf_id,lf_interpretation);
+ },
+ SymbexResult::UnSAT => {
+ panic!("UnSAT at initialization step on lifeline {}", lf_name);
+ }
+ }
+ }
+ return div_ec_id;
+}
\ No newline at end of file
diff --git a/src/grpc_connect/mod.rs b/src/grpc_connect/mod.rs
new file mode 100644
index 0000000..fca8068
--- /dev/null
+++ b/src/grpc_connect/mod.rs
@@ -0,0 +1,20 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod from_grpc;
+pub mod to_grpc;
+pub mod calls;
+pub mod xlia_reference_name_tools;
+pub mod init_calls;
+pub mod post_process;
\ No newline at end of file
diff --git a/src/grpc_connect/post_process.rs b/src/grpc_connect/post_process.rs
new file mode 100644
index 0000000..02e9d62
--- /dev/null
+++ b/src/grpc_connect/post_process.rs
@@ -0,0 +1,40 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashSet;
+use std::collections::btree_map::BTreeMap;
+
+use crate::diversity::symbex_client::SymbexClient;
+use crate::diversity::model_definition_request::ModelAlt;
+use crate::diversity::*;
+
+
+
+use crate::grpc_connect::xlia_reference_name_tools::*;
+use crate::grpc_connect::calls::*;
+
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+
+pub async fn symbex_post_process(client : &mut SymbexClient<tonic::transport::Channel>) {
+
+ // ***
+ let post_process_request = tonic::Request::new(PostProcessingRequest {
+ enable_execution_graph: true,
+ });
+ println!("POST PROCESS REQUEST = {:?}", post_process_request);
+ let pose_process_response = client.run_post_processor(post_process_request).await.unwrap();
+ let post_process_reply = pose_process_response.into_inner();
+ println!("POST PROCESS REPLY = {:?}", post_process_reply );
+ // ***
+}
\ No newline at end of file
diff --git a/src/grpc_connect/to_grpc.rs b/src/grpc_connect/to_grpc.rs
new file mode 100644
index 0000000..9198c27
--- /dev/null
+++ b/src/grpc_connect/to_grpc.rs
@@ -0,0 +1,266 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::core::syntax::data::var_ref::VariableReference;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::builtin::bool::*;
+use crate::core::syntax::data::builtin::number::*;
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::float::TD_Float;
+use crate::core::syntax::data::builtin::string::TD_String;
+
+use crate::diversity::*;
+use crate::diversity::expression::ExpressionAlt;
+
+use crate::grpc_connect::xlia_reference_name_tools::*;
+
+pub fn td_generic_to_grpc(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize, td_gen : &TD_Generic) -> Expression {
+ match td_gen {
+ TD_Generic::Bool(td_bool) => {
+ return td_bool_to_grpc(gen_ctx, exe_ctx, lf_id,td_bool);
+ },
+ TD_Generic::String(td_string) => {
+ return td_string_to_grpc(gen_ctx, exe_ctx, lf_id,td_string);
+ },
+ TD_Generic::Integer(td_int) => {
+ return td_int_to_grpc(gen_ctx, exe_ctx, lf_id,td_int);
+ },
+ TD_Generic::Float(td_float) => {
+ return td_float_to_grpc(gen_ctx, exe_ctx, lf_id,td_float);
+ }
+ }
+}
+
+fn var_ref_to_grpc(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize, var_ref : &VariableReference) -> Expression {
+ match var_ref {
+ VariableReference::VARIABLE( var_id ) => {
+ let (_,var_child_idx) = exe_ctx.get_vr_parent_name_and_child_id(gen_ctx, *var_id).unwrap();
+ let fqn = variable_diversity_fqn(gen_ctx,exe_ctx,lf_id,*var_id);
+ let expr_kind = ExpressionAlt::VariableId(fqn);
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ VariableReference::SYMBOL( symb_id ) => {
+ let symbol_diversity_name = exe_ctx.get_sy_diversity_name( *symb_id).unwrap();
+ let expr_kind = ExpressionAlt::SymbolId(symbol_diversity_name);
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ _ => {
+ panic!();
+ }
+ }
+}
+
+
+
+fn td_int_to_grpc(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize, td_int : &TD_Integer) -> Expression {
+ match td_int {
+ TD_Integer::Value( value ) => {
+ let expr_kind = ExpressionAlt::RawInteger( *value );
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ TD_Integer::Reference(var_ref) => {
+ return var_ref_to_grpc(gen_ctx,exe_ctx,lf_id,var_ref);
+ },
+ TD_Integer::Minus( minused ) => {
+ let minused_td_int = td_int_to_grpc(gen_ctx,exe_ctx,lf_id,&*minused);
+ let minus_op = ExpressionAlt::Operation(Operation{operator_kind:OperatorKind::Uminus as i32,operand:vec![minused_td_int]});
+ let minus_sub_expr = Expression{expression_alt:Some( minus_op )};
+ return minus_sub_expr;
+ }
+ TD_Integer::Add( adds ) => {
+ let mut operand : Vec<Expression> = Vec::new();
+ for (add_sign,sub_int) in adds {
+ let sub_int_expr = td_int_to_grpc(gen_ctx,exe_ctx,lf_id,sub_int);
+ match add_sign {
+ ARITH_ADD_SIGN::Plus => {
+ operand.push(sub_int_expr);
+ },
+ ARITH_ADD_SIGN::Minus => {
+ let minus_op = ExpressionAlt::Operation(Operation{operator_kind:OperatorKind::Uminus as i32,operand:vec![sub_int_expr]});
+ let minus_sub_expr = Expression{expression_alt:Some( minus_op )};
+ operand.push(minus_sub_expr);
+ }
+ }
+ }
+ let ex_alt = ExpressionAlt::Operation( Operation{operator_kind: (OperatorKind::Add as i32) , operand} );
+ return Expression{expression_alt:Some(ex_alt)};
+ },
+ TD_Integer::Factor( factor ) => {
+ let mut operand : Vec<Expression> = Vec::new();
+ for (fact_sign,sub_int) in factor {
+ let sub_int_expr = td_int_to_grpc(gen_ctx,exe_ctx,lf_id,sub_int);
+ match fact_sign {
+ ARITH_FACTOR_SIGN::Mult => {
+ operand.push(sub_int_expr);
+ },
+ ARITH_FACTOR_SIGN::Div => {
+ let integer_one = Expression{expression_alt:Some( ExpressionAlt::RawInteger(1 as i64) )};
+ let division_op = ExpressionAlt::Operation(Operation{operator_kind:OperatorKind::Div as i32,operand:vec![integer_one,sub_int_expr]});
+ let division_sub_expr = Expression{expression_alt:Some( division_op )};
+ operand.push(division_sub_expr);
+ }
+ }
+ }
+ let ex_alt = ExpressionAlt::Operation( Operation{operator_kind: (OperatorKind::Mult as i32) , operand} );
+ return Expression{expression_alt:Some(ex_alt)};
+ }
+ }
+}
+
+fn td_float_to_grpc(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize, td_float : &TD_Float) -> Expression {
+ match td_float {
+ TD_Float::Value( value ) => {
+ let expr_kind = ExpressionAlt::RawFloat( *value );
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ TD_Float::Reference(var_ref) => {
+ return var_ref_to_grpc(gen_ctx,exe_ctx,lf_id,var_ref);
+ },
+ TD_Float::Minus( minused ) => {
+ let minused_td_int = td_float_to_grpc(gen_ctx,exe_ctx,lf_id,&*minused);
+ let minus_op = ExpressionAlt::Operation(Operation{operator_kind:OperatorKind::Uminus as i32,operand:vec![minused_td_int]});
+ let minus_sub_expr = Expression{expression_alt:Some( minus_op )};
+ return minus_sub_expr;
+ }
+ TD_Float::Add( adds ) => {
+ let mut operand : Vec<Expression> = Vec::new();
+ for (add_sign,sub_int) in adds {
+ let sub_int_expr = td_float_to_grpc(gen_ctx,exe_ctx,lf_id,sub_int);
+ match add_sign {
+ ARITH_ADD_SIGN::Plus => {
+ operand.push(sub_int_expr);
+ },
+ ARITH_ADD_SIGN::Minus => {
+ let minus_op = ExpressionAlt::Operation(Operation{operator_kind:OperatorKind::Uminus as i32,operand:vec![sub_int_expr]});
+ let minus_sub_expr = Expression{expression_alt:Some( minus_op )};
+ operand.push(minus_sub_expr);
+ }
+ }
+ }
+ let ex_alt = ExpressionAlt::Operation( Operation{operator_kind: (OperatorKind::Add as i32) , operand} );
+ return Expression{expression_alt:Some(ex_alt)};
+ },
+ TD_Float::Factor( factor ) => {
+ let mut operand : Vec<Expression> = Vec::new();
+ for (fact_sign,sub_int) in factor {
+ let sub_int_expr = td_float_to_grpc(gen_ctx,exe_ctx,lf_id,sub_int);
+ match fact_sign {
+ ARITH_FACTOR_SIGN::Mult => {
+ operand.push(sub_int_expr);
+ },
+ ARITH_FACTOR_SIGN::Div => {
+ let float_one = Expression{expression_alt:Some( ExpressionAlt::RawFloat(1.0 as f64) )};
+ let division_op = ExpressionAlt::Operation(Operation{operator_kind:OperatorKind::Div as i32,operand:vec![float_one,sub_int_expr]});
+ let division_sub_expr = Expression{expression_alt:Some( division_op )};
+ operand.push(division_sub_expr);
+ }
+ }
+ }
+ let ex_alt = ExpressionAlt::Operation( Operation{operator_kind: (OperatorKind::Mult as i32) , operand} );
+ return Expression{expression_alt:Some(ex_alt)};
+ }
+ }
+}
+
+fn td_string_to_grpc(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize, td_string : &TD_String) -> Expression {
+ match td_string {
+ TD_String::Reference(var_ref) => {
+ return var_ref_to_grpc(gen_ctx,exe_ctx,lf_id,var_ref);
+ },
+ TD_String::Value( value ) => {
+ let expr_kind = ExpressionAlt::RawString( value.clone() );
+ return Expression{expression_alt:Some(expr_kind)};
+ }
+ }
+}
+
+
+pub fn td_bool_to_grpc(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize, td_bool : &TD_Bool) -> Expression {
+ match td_bool {
+ TD_Bool::TRUE => {
+ let expr_kind = ExpressionAlt::RawBool(true);
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ TD_Bool::FALSE => {
+ let expr_kind = ExpressionAlt::RawBool(false);
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ TD_Bool::AND(sub_bools) => {
+ let mut sub_exprs : Vec<Expression> = Vec::new();
+ for sub_bool in sub_bools {
+ sub_exprs.push( td_bool_to_grpc(gen_ctx,exe_ctx,lf_id,sub_bool) );
+ }
+ let operation = Operation{operator_kind: (OperatorKind::And as i32) , operand:sub_exprs};
+ let expr_kind = ExpressionAlt::Operation(operation);
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ TD_Bool::OR(sub_bools) => {
+ let mut sub_exprs : Vec<Expression> = Vec::new();
+ for sub_bool in sub_bools {
+ sub_exprs.push( td_bool_to_grpc(gen_ctx,exe_ctx,lf_id,sub_bool) );
+ }
+ let operation = Operation{operator_kind: (OperatorKind::Or as i32) , operand:sub_exprs};
+ let expr_kind = ExpressionAlt::Operation(operation);
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ TD_Bool::NOT(sub_bool) => {
+ let operation = Operation{operator_kind: (OperatorKind::Not as i32) , operand:vec![ td_bool_to_grpc(gen_ctx,exe_ctx,lf_id,&*sub_bool) ]};
+ let expr_kind = ExpressionAlt::Operation(operation);
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ TD_Bool::COMPARE(bool_compare,first,second) => {
+ let first_expression = td_generic_to_grpc(gen_ctx,exe_ctx,lf_id,&*first);
+ let second_expression = td_generic_to_grpc(gen_ctx,exe_ctx,lf_id,&*first);
+ match bool_compare {
+ Bool_Compare::Equal => {
+ let operation = Operation{operator_kind: (OperatorKind::Eq as i32) , operand:vec![ first_expression,second_expression ]};
+ let expr_kind = ExpressionAlt::Operation(operation);
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ Bool_Compare::Different => {
+ let operation = Operation{operator_kind: (OperatorKind::Neq as i32) , operand:vec![ first_expression,second_expression ]};
+ let expr_kind = ExpressionAlt::Operation(operation);
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ Bool_Compare::Greater => {
+ let operation = Operation{operator_kind: (OperatorKind::Gt as i32) , operand:vec![ first_expression,second_expression ]};
+ let expr_kind = ExpressionAlt::Operation(operation);
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ Bool_Compare::GreaterOrEqual => {
+ let operation = Operation{operator_kind: (OperatorKind::Gte as i32) , operand:vec![ first_expression,second_expression ]};
+ let expr_kind = ExpressionAlt::Operation(operation);
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ Bool_Compare::Lower => {
+ let operation = Operation{operator_kind: (OperatorKind::Lt as i32) , operand:vec![ first_expression,second_expression ]};
+ let expr_kind = ExpressionAlt::Operation(operation);
+ return Expression{expression_alt:Some(expr_kind)};
+ },
+ Bool_Compare::LowerOrEqual => {
+ let operation = Operation{operator_kind: (OperatorKind::Lte as i32) , operand:vec![ first_expression,second_expression ]};
+ let expr_kind = ExpressionAlt::Operation(operation);
+ return Expression{expression_alt:Some(expr_kind)};
+ }
+ }
+ },
+ TD_Bool::Reference( var_ref ) => {
+ return var_ref_to_grpc(gen_ctx,exe_ctx,lf_id,var_ref);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/grpc_connect/xlia_reference_name_tools.rs b/src/grpc_connect/xlia_reference_name_tools.rs
new file mode 100644
index 0000000..9ca2ee3
--- /dev/null
+++ b/src/grpc_connect/xlia_reference_name_tools.rs
@@ -0,0 +1,68 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashMap;
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::interaction::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::td_type::TD_DataType;
+
+use crate::tools::fold_vec_to_string;
+
+pub fn action_diversity_fqn(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize, relative_position : &Vec<u32>) -> String {
+ let lf_name = exe_ctx.get_lf_name(gen_ctx,lf_id).unwrap();
+ return format!("{}.action_{}",lf_name,fold_vec_to_string(relative_position));
+}
+
+pub fn trace_action_compare_diversity_fqn(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize, ms_id : usize) -> String {
+ let lf_name = exe_ctx.get_lf_name(gen_ctx,lf_id).unwrap();
+ let ms_name= gen_ctx.get_ms_name(ms_id).unwrap();
+ return format!("{}.action_compare_ms_{}",lf_name,ms_name);
+}
+
+pub fn open_scopes_action_diversity_fqn(gen_ctx : &GeneralContext, lf_id : usize) -> String {
+ let lf_name = gen_ctx.get_lf_name(lf_id).unwrap();
+ return format!("{}.action_open_scopes",lf_name);
+}
+
+pub fn message_parameter_diversity_fqn(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize, ms_id : usize, pr_id : usize) -> String {
+ let lf_name = exe_ctx.get_lf_name(gen_ctx,lf_id).unwrap();
+ let ms_name= gen_ctx.get_ms_name(ms_id).unwrap();
+ return format!("{}.ms_{}_pr_{}",lf_name,ms_name,pr_id);
+}
+
+pub fn trace_message_parameter_diversity_fqn(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize, ms_id : usize, pr_id : usize) -> String {
+ let lf_name = exe_ctx.get_lf_name(gen_ctx,lf_id).unwrap();
+ let ms_name= gen_ctx.get_ms_name(ms_id).unwrap();
+ return format!("{}.trace_ms_{}_pr_{}",lf_name,ms_name,pr_id);
+}
+
+pub fn trace_delay_diversity_fqn(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize) -> String {
+ let lf_name = exe_ctx.get_lf_name(gen_ctx,lf_id).unwrap();
+ return format!("{}.trace_delay",lf_name);
+}
+
+pub fn variable_diversity_fqn(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize, vr_id : usize) -> String {
+ let lf_name = exe_ctx.get_lf_name(gen_ctx,lf_id).unwrap();
+ let (parent_var_name, var_index) = exe_ctx.get_vr_parent_name_and_child_id(gen_ctx,vr_id).unwrap();
+ return format!("{}.lf_var_{}[{}]",lf_name,parent_var_name,var_index);
+}
+
+pub fn varindex_diversity_fqn(gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext, lf_id : usize, vr_id : usize) -> String {
+ let lf_name = exe_ctx.get_lf_name(gen_ctx,lf_id).unwrap();
+ let (parent_var_name,_) = exe_ctx.get_vr_parent_name_and_child_id(gen_ctx,vr_id).unwrap();
+ return format!("{}.index_{}",lf_name,parent_var_name);
+}
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..e7f926a
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,61 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+extern crate strum;
+
+#[macro_use]
+extern crate strum_macros;
+
+extern crate rusttype;
+
+extern crate image;
+
+extern crate imageproc;
+
+extern crate pest;
+
+#[macro_use]
+extern crate pest_derive;
+
+#[macro_use]
+extern crate clap;
+
+extern crate tonic;
+
+extern crate prost;
+
+extern crate bytes;
+
+// **********
+
+pub mod tools;
+pub mod core;
+pub mod from_text;
+pub mod rendering;
+pub mod process;
+pub mod ui;
+pub mod diversity;
+pub mod grpc_connect;
+pub mod xlia;
+// **********
+
+use crate::ui::hibou_cli::hibou_cli;
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+ hibou_cli().await;
+ return Ok(());
+}
+
+
diff --git a/src/process/analysis.rs b/src/process/analysis.rs
new file mode 100644
index 0000000..2cf1961
--- /dev/null
+++ b/src/process/analysis.rs
@@ -0,0 +1,204 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::BTreeMap;
+use std::collections::{HashSet,HashMap};
+use std::fs;
+use std::fs::File;
+use std::io::{Read,BufReader,BufRead,BufWriter,Write};
+use std::iter::FromIterator;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::core::syntax::interaction::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::position::*;
+
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::core::syntax::data::generic::TD_Generic;
+
+use crate::core::trace::*;
+use crate::core::semantics::frontier::make_frontier;
+use crate::core::semantics::shape_execute::shape_execute;
+
+use crate::process::verdicts::*;
+use crate::process::log::ProcessLogger;
+use crate::process::hibou_process::*;
+use crate::process::process_manager::*;
+use crate::process::deploy_receptions::deploy_original_action_followup;
+use crate::process::queue::ProcessQueue;
+
+use crate::xlia::model::generate_xlia_model;
+
+use crate::grpc_connect::calls::*;
+use crate::grpc_connect::init_calls::*;
+use crate::grpc_connect::post_process::*;
+use crate::grpc_connect::to_grpc::{td_generic_to_grpc,td_bool_to_grpc};
+use crate::grpc_connect::xlia_reference_name_tools::*;
+
+use crate::diversity::symbex_client::SymbexClient;
+use crate::diversity::*;
+
+pub async fn analyze(interaction : Interaction,
+ multi_trace : AnalysableMultiTrace,
+ gen_ctx : GeneralContext,
+ exe_ctx : ExecutionContext,
+ temporality : HibouProcessTemporality,
+ pre_filters : Vec<HibouPreFilter>,
+ strategy : HibouSearchStrategy,
+ frontier_priorities : ProcessPriorities,
+ loggers : Vec<Box<dyn ProcessLogger>>,
+ goal:GlobalVerdict) -> GlobalVerdict {
+ // ***
+ let mut first_context = exe_ctx;
+ let xlia_model_string = generate_xlia_model(&gen_ctx,&first_context,&interaction, &temporality);
+ let model_file_path = "xlia_model.xlia".to_string();
+ let mut file = File::create(&model_file_path).unwrap();
+ file.write( xlia_model_string.as_bytes() );
+ println!("generated xlia model :\n{}",xlia_model_string);
+ // ***
+ let (mut client,mut initial_div_ec_id) = symbex_init_model(&gen_ctx,&mut first_context,xlia_model_string).await;
+ // ***
+ initial_div_ec_id = symbex_fire_lifeline_initializations(&mut client, &gen_ctx,&mut first_context,initial_div_ec_id).await;
+ // ***
+ let mut manager = HibouProcessManager::new(gen_ctx,
+ strategy,
+ temporality,
+ pre_filters,
+ HashMap::new(),
+ ProcessQueue::new(),
+ frontier_priorities,
+ loggers);
+ // ***
+ let multi_trace_option = Some(multi_trace);
+ manager.init_loggers(&first_context,&interaction,&multi_trace_option);
+ let multi_trace = multi_trace_option.unwrap();
+ // ***
+ let mut next_state_id : u32 = 1;
+ let mut node_counter : u32 = 0;
+ let mut global_verdict = GlobalVerdict::Fail;
+ // ***
+ match enqueue_next_node_in_analysis(&mut manager,
+ next_state_id,
+ initial_div_ec_id,
+ first_context,
+ interaction,
+ multi_trace,0,0) {
+ None => {},
+ Some( coverage_verdict ) => {
+ global_verdict = update_global_verdict_from_new_coverage_verdict(global_verdict, coverage_verdict);
+ }
+ }
+ next_state_id = next_state_id +1;
+ node_counter = node_counter +1;
+ // ***
+ if global_verdict < goal {
+ while let Some(next_to_process) = manager.extract_from_queue() {
+ let new_state_id = next_state_id;
+ next_state_id = next_state_id + 1;
+ // ***
+ let mut parent_state = manager.get_memorized_state(next_to_process.state_id).unwrap().clone();
+ // ***
+ match manager.process_next(&mut client,
+ &parent_state,
+ &next_to_process,
+ new_state_id,
+ node_counter).await {
+ None => {},
+ Some( (new_interaction,new_exe_ctx,new_div_ec_id,new_multi_trace,new_depth,new_loop_depth) ) => {
+ node_counter = node_counter + 1;
+ match enqueue_next_node_in_analysis(&mut manager,
+ new_state_id,
+ new_div_ec_id,
+ new_exe_ctx,
+ new_interaction,
+ new_multi_trace.unwrap(),
+ new_depth,
+ new_loop_depth) {
+ None => {},
+ Some( coverage_verdict ) => {
+ global_verdict = update_global_verdict_from_new_coverage_verdict(global_verdict, coverage_verdict);
+ if global_verdict >= goal {
+ break;
+ }
+ }
+ }
+ }
+ }
+ // ***
+ parent_state.remaining_ids_to_process.remove(&next_to_process.id_as_child);
+ if parent_state.remaining_ids_to_process.len() == 0 {
+ manager.forget_state(next_to_process.state_id);
+ } else {
+ manager.remember_state(next_to_process.state_id,parent_state);
+ }
+ // ***
+ }
+ }
+ // ***
+ symbex_post_process(&mut client).await;
+ // ***
+ manager.term_loggers(Some((&goal,&global_verdict)) );
+ // ***
+ return global_verdict;
+}
+
+fn enqueue_next_node_in_analysis(manager : &mut HibouProcessManager,
+ state_id : u32,
+ diversity_ec_id : u32,
+ exe_ctx : ExecutionContext,
+ interaction : Interaction,
+ multi_trace : AnalysableMultiTrace,
+ depth : u32,
+ loop_depth : u32) -> Option<CoverageVerdict> {
+ // ***
+ let mut next_child_id : u32 = 0;
+ // ***
+ let mut to_enqueue : Vec<(u32,NextToProcessKind)> = Vec::new();
+ for front_pos in make_frontier(&interaction) {
+ let front_act = interaction.get_sub_interaction(&front_pos).as_leaf();
+ for canal in &multi_trace.canals {
+ if canal.trace.len() > 0 {
+ let head_act : &TraceAction = canal.trace.get(0).unwrap();
+ if head_act.is_signature_match(front_act) {
+ next_child_id = next_child_id +1;
+ let child_kind = NextToProcessKind::Execute(front_pos);
+ to_enqueue.push( (next_child_id,child_kind) );
+ break;
+ }
+ }
+ }
+ }
+ // ***
+ if next_child_id > 0 {
+ let rem_child_ids : HashSet<u32> = HashSet::from_iter((1..(next_child_id+1)).collect::<Vec<u32>>().iter().cloned() );
+ let memo_state = MemorizedState::new(interaction,
+ exe_ctx,
+ diversity_ec_id,
+ Some(multi_trace),
+ rem_child_ids,
+ loop_depth, depth);
+ manager.remember_state( state_id, memo_state );
+ manager.enqueue_executions(state_id,to_enqueue);
+ return None;
+ } else {
+ let verdict = manager.get_coverage_verdict(&interaction,&multi_trace);
+ manager.verdict_loggers(&verdict,state_id);
+ return Some( verdict );
+ }
+}
+
+
diff --git a/src/process/deploy_receptions.rs b/src/process/deploy_receptions.rs
new file mode 100644
index 0000000..35b39a6
--- /dev/null
+++ b/src/process/deploy_receptions.rs
@@ -0,0 +1,82 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::interaction::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::position::*;
+
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::core::syntax::data::generic::TD_Generic;
+
+
+pub fn deploy_original_action_followup(exe_ctx : &ExecutionContext,
+ interaction : &Interaction,
+ position : &Position,
+ model_action : &ObservableAction,
+ effective_parameters : &Vec<TD_Generic>) -> Interaction {
+ let to_substitute : Interaction;
+ match &model_action.act_kind {
+ ObservableActionKind::Reception => {
+ to_substitute = Interaction::Empty;
+ },
+ ObservableActionKind::Emission( targets ) => {
+ let params = effective_parameters.iter().map(|x| ValueOrNewFresh::Value(x.clone()) ).collect();;
+ to_substitute = deploy_receptions(exe_ctx,0,targets, &model_action.ms_id, ¶ms, (model_action.original_position).as_ref().unwrap());
+ }
+ }
+ return interaction.substitute(to_substitute,position);
+}
+
+
+fn deploy_receptions(exe_ctx : &ExecutionContext, index : usize, targets : &Vec<LifelineAction>, ms_id : &usize, params : &Vec<ValueOrNewFresh>, parent_original : &Vec<u32>) -> Interaction {
+ let tar_len = targets.len();
+ if index >= tar_len {
+ return Interaction::Empty;
+ } else if index == tar_len -1 {
+ let lf_act = targets.get(index).unwrap();
+ return deploy_lf_act(exe_ctx, lf_act, ms_id, params, parent_original,index as u32);
+ } else {
+ let head_lf_act = targets.get(index).unwrap();
+ let head_int = deploy_lf_act(exe_ctx, head_lf_act, ms_id, params,parent_original,index as u32);
+ match &head_int {
+ &Interaction::Empty => {
+ return deploy_receptions(exe_ctx,index+1,targets, ms_id, params,parent_original);
+ },
+ _ => {
+ return Interaction::Par(Box::new(head_int),
+ Box::new(deploy_receptions(exe_ctx,index+1,targets, ms_id, params,parent_original)));
+ }
+ }
+ }
+}
+
+fn deploy_lf_act(exe_ctx : &ExecutionContext,
+ lf_act : &LifelineAction,
+ ms_id : &usize,
+ params : &Vec<ValueOrNewFresh>,
+ parent_original : &Vec<u32>,
+ index : u32) -> Interaction {
+ let mut original = parent_original.clone();
+ original.push(index + 1);
+ return Interaction::Action( ObservableAction{
+ lf_act:lf_act.clone(),
+ act_kind:ObservableActionKind::Reception,
+ ms_id:*ms_id,
+ params:params.clone(),
+ original_position:Some(original.clone()) });
+}
+
diff --git a/src/process/exploration.rs b/src/process/exploration.rs
new file mode 100644
index 0000000..a194d27
--- /dev/null
+++ b/src/process/exploration.rs
@@ -0,0 +1,170 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::BTreeMap;
+use std::collections::{HashSet,HashMap};
+use std::fs;
+use std::fs::File;
+use std::io::{Read,BufReader,BufRead,BufWriter,Write};
+use std::iter::FromIterator;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::core::syntax::interaction::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::position::*;
+
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::core::syntax::data::generic::TD_Generic;
+
+use crate::core::trace::*;
+use crate::core::semantics::frontier::make_frontier;
+use crate::core::semantics::shape_execute::shape_execute;
+
+use crate::process::verdicts::*;
+use crate::process::log::ProcessLogger;
+use crate::process::hibou_process::*;
+use crate::process::process_manager::*;
+use crate::process::deploy_receptions::deploy_original_action_followup;
+
+use crate::xlia::model::generate_xlia_model;
+
+use crate::grpc_connect::calls::*;
+use crate::grpc_connect::init_calls::*;
+use crate::grpc_connect::post_process::*;
+use crate::grpc_connect::to_grpc::{td_generic_to_grpc,td_bool_to_grpc};
+use crate::grpc_connect::xlia_reference_name_tools::*;
+
+use crate::diversity::symbex_client::SymbexClient;
+use crate::diversity::*;
+
+use crate::process::queue::ProcessQueue;
+
+pub async fn explore(interaction : Interaction,
+ gen_ctx : GeneralContext,
+ exe_ctx : ExecutionContext,
+ temporality : HibouProcessTemporality,
+ pre_filters : Vec<HibouPreFilter>,
+ strategy : HibouSearchStrategy,
+ frontier_priorities : ProcessPriorities,
+ loggers : Vec<Box<dyn ProcessLogger>>) {
+ // ***
+ let mut first_context = exe_ctx;
+ let xlia_model_string = generate_xlia_model(&gen_ctx,&first_context,&interaction, &temporality);
+ let model_file_path = "xlia_model.xlia".to_string();
+ let mut file = File::create(&model_file_path).unwrap();
+ file.write( xlia_model_string.as_bytes() );
+ println!("generated xlia model :\n{}",xlia_model_string);
+ // ***
+ let (mut client,mut initial_div_ec_id) = symbex_init_model(&gen_ctx,&mut first_context,xlia_model_string).await;
+ // ***
+ initial_div_ec_id = symbex_fire_lifeline_initializations(&mut client, &gen_ctx,&mut first_context,initial_div_ec_id).await;
+ // ***
+ let mut manager = HibouProcessManager::new(gen_ctx,
+ strategy,
+ temporality,
+ pre_filters,
+ HashMap::new(),
+ ProcessQueue::new(),
+ frontier_priorities,
+ loggers);
+ // ***
+ manager.init_loggers(&first_context,&interaction,&None);
+ // ***
+ let mut next_state_id : u32 = 1;
+ let mut node_counter : u32 = 0;
+ enqueue_next_node_in_exploration(&mut manager,
+ next_state_id,
+ initial_div_ec_id,
+ first_context,
+ interaction,0,0);
+ next_state_id = next_state_id + 1;
+ node_counter = node_counter +1;
+ // ***
+ // ***
+ while let Some(next_to_process) = manager.extract_from_queue() {
+ let new_state_id = next_state_id;
+ next_state_id = next_state_id + 1;
+ // ***
+ let mut parent_state = manager.get_memorized_state(next_to_process.state_id).unwrap().clone();
+ // ***
+ match manager.process_next(&mut client,
+ &parent_state,
+ &next_to_process,
+ new_state_id,
+ node_counter).await {
+ None => {},
+ Some( (new_interaction,new_exe_ctx,new_div_ec_id,new_multi_trace,new_depth,new_loop_depth) ) => {
+ node_counter = node_counter + 1;
+ enqueue_next_node_in_exploration(&mut manager,
+ new_state_id,
+ new_div_ec_id,
+ new_exe_ctx,
+ new_interaction,
+ new_depth,
+ new_loop_depth);
+ }
+ }
+ // ***
+ parent_state.remaining_ids_to_process.remove(&next_to_process.id_as_child);
+ if parent_state.remaining_ids_to_process.len() == 0 {
+ manager.forget_state(next_to_process.state_id);
+ } else {
+ manager.remember_state(next_to_process.state_id,parent_state);
+ }
+ // ***
+ }
+ // ***
+ symbex_post_process(&mut client).await;
+ // ***
+ manager.term_loggers(None);
+ // ***
+}
+
+
+
+fn enqueue_next_node_in_exploration(manager : &mut HibouProcessManager,
+ state_id : u32,
+ diversity_ec_id : u32,
+ exe_ctx : ExecutionContext,
+ interaction : Interaction,
+ depth : u32,
+ loop_depth : u32) {
+ // ***
+ let mut next_child_id : u32 = 0;
+ // ***
+ let mut to_enqueue : Vec<(u32,NextToProcessKind)> = Vec::new();
+ for front_pos in make_frontier(&interaction) {
+ next_child_id = next_child_id +1;
+ let child_kind = NextToProcessKind::Execute(front_pos);
+ to_enqueue.push( (next_child_id,child_kind) );
+ }
+ // ***
+ if next_child_id > 0 {
+ let rem_child_ids : HashSet<u32> = HashSet::from_iter((1..(next_child_id+1)).collect::<Vec<u32>>().iter().cloned() );
+ let memo_state = MemorizedState::new(interaction,
+ exe_ctx,
+ diversity_ec_id,
+ None,
+ rem_child_ids,
+ loop_depth,depth);
+ manager.remember_state( state_id, memo_state );
+ manager.enqueue_executions( state_id, to_enqueue );
+ }
+}
+
+
+
diff --git a/src/process/hibou_process.rs b/src/process/hibou_process.rs
new file mode 100644
index 0000000..695dec9
--- /dev/null
+++ b/src/process/hibou_process.rs
@@ -0,0 +1,181 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::cmp::Reverse;
+use std::collections::{HashSet,HashMap};
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::interaction::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::position::*;
+use crate::core::trace::*;
+use crate::process::log::ProcessLogger;
+use crate::core::semantics::frontier::make_frontier;
+use crate::core::semantics::shape_execute::shape_execute;
+
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+
+
+#[derive(Clone, PartialEq, Debug)]
+pub struct MemorizedState {
+ pub interaction : Interaction,
+ pub exe_ctx : ExecutionContext,
+ pub diversity_ec_id : u32,
+ pub multi_trace : Option<AnalysableMultiTrace>,
+ pub remaining_ids_to_process : HashSet<u32>,
+ pub loop_depth : u32, // number of loop instanciations since intial interaction
+ pub depth : u32 // number of execution steps since initial interaction
+}
+
+impl MemorizedState {
+ pub fn new(interaction : Interaction,
+ exe_ctx : ExecutionContext,
+ diversity_ec_id : u32,
+ multi_trace : Option<AnalysableMultiTrace>,
+ remaining_ids_to_process : HashSet<u32>,
+ loop_depth : u32,
+ depth : u32) -> MemorizedState {
+ return MemorizedState{interaction,exe_ctx,diversity_ec_id,multi_trace,remaining_ids_to_process,loop_depth,depth};
+ }
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub enum NextToProcessKind {
+ Execute(Position)
+}
+
+#[derive(Clone, PartialEq, Debug)]
+pub struct NextToProcess {
+ pub state_id : u32,
+ pub id_as_child : u32,
+ pub kind : NextToProcessKind
+}
+
+impl NextToProcess {
+ pub fn new(state_id : u32,
+ id_as_child : u32,
+ kind : NextToProcessKind) -> NextToProcess {
+ return NextToProcess{state_id,id_as_child,kind};
+ }
+}
+
+
+
+pub enum HibouPreFilter {
+ MaxLoopInstanciation(u32),
+ MaxProcessDepth(u32),
+ MaxNodeNumber(u32)
+}
+
+impl std::string::ToString for HibouPreFilter {
+ fn to_string(&self) -> String {
+ match self {
+ HibouPreFilter::MaxLoopInstanciation(num) => {
+ return format!("MaxLoop={}",num);
+ },
+ HibouPreFilter::MaxProcessDepth(num) => {
+ return format!("MaxDepth={}",num);
+ },
+ HibouPreFilter::MaxNodeNumber(num) => {
+ return format!("MaxNum={}",num);
+ }
+ }
+ }
+}
+
+pub enum FilterEliminationKind {
+ MaxLoopInstanciation,
+ MaxProcessDepth,
+ MaxNodeNumber
+}
+
+impl std::string::ToString for FilterEliminationKind {
+ fn to_string(&self) -> String {
+ match self {
+ FilterEliminationKind::MaxLoopInstanciation => {
+ return "MaxLoop".to_string();
+ },
+ FilterEliminationKind::MaxProcessDepth => {
+ return "MaxDepth".to_string();
+ },
+ FilterEliminationKind::MaxNodeNumber => {
+ return "MaxNum".to_string();
+ }
+ }
+ }
+}
+
+
+pub enum HibouSearchStrategy {
+ BFS,
+ DFS
+}
+
+impl std::string::ToString for HibouSearchStrategy {
+ fn to_string(&self) -> String {
+ match self {
+ HibouSearchStrategy::BFS => {
+ return "Breadth First Search".to_string();
+ },
+ HibouSearchStrategy::DFS => {
+ return "Depth First Search".to_string();
+ }
+ }
+ }
+}
+
+
+pub enum HibouProcessTemporality {
+ Timed,
+ UnTimed
+}
+
+impl std::string::ToString for HibouProcessTemporality {
+ fn to_string(&self) -> String {
+ match self {
+ HibouProcessTemporality::Timed => {
+ return "Timed".to_string();
+ },
+ HibouProcessTemporality::UnTimed => {
+ return "UnTimed".to_string();
+ }
+ }
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/process/log.rs b/src/process/log.rs
new file mode 100644
index 0000000..d0383f5
--- /dev/null
+++ b/src/process/log.rs
@@ -0,0 +1,79 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashMap;
+
+// ***
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::core::syntax::position::*;
+use crate::core::syntax::interaction::Interaction;
+use crate::core::syntax::action::*;
+use crate::core::context::general::GeneralContext;
+
+use crate::core::context::execution::ExecutionContext;
+use crate::core::trace::*;
+
+
+use crate::process::hibou_process::FilterEliminationKind;
+
+use crate::process::verdicts::*;
+
+
+
+pub trait ProcessLogger {
+
+ fn log_init(&mut self,
+ interaction : &Interaction,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ remaining_multi_trace : &Option<AnalysableMultiTrace>);
+
+ fn log_term(&mut self,
+ options_as_str : &Vec<String>);
+
+ fn log_execution(&mut self,
+ gen_ctx : &GeneralContext,
+ parent_state_id : u32,
+ new_state_id : u32,
+ action_position : &Position,
+ trace_action : Option<&TraceAction>,
+ model_action : &ObservableAction,
+ new_interaction : &Interaction,
+ new_exe_ctx : &ExecutionContext,
+ remaining_multi_trace : &Option<AnalysableMultiTrace>);
+
+ fn log_verdict(&mut self,
+ parent_state_id : u32,
+ verdict : &CoverageVerdict);
+
+ fn log_filtered(&mut self,
+ gen_ctx : &GeneralContext,
+ exe_ctx:&ExecutionContext,
+ parent_state_id : u32,
+ new_state_id : u32,
+ action_position : &Position,
+ action : &ObservableAction,
+ elim_kind : &FilterEliminationKind);
+
+ fn log_unsat(&mut self,
+ gen_ctx : &GeneralContext,
+ exe_ctx:&ExecutionContext,
+ parent_state_id : u32,
+ new_state_id : u32,
+ action_position : &Position,
+ trace_action : Option<&TraceAction>,
+ model_action : &ObservableAction);
+}
+
diff --git a/src/process/mod.rs b/src/process/mod.rs
new file mode 100644
index 0000000..e68222e
--- /dev/null
+++ b/src/process/mod.rs
@@ -0,0 +1,27 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+pub mod symbex;
+
+pub mod log;
+pub mod hibou_process;
+pub mod process_manager;
+pub mod deploy_receptions;
+pub mod verdicts;
+pub mod queue;
+
+pub mod exploration;
+pub mod analysis;
+
diff --git a/src/process/process_manager.rs b/src/process/process_manager.rs
new file mode 100644
index 0000000..6ed644e
--- /dev/null
+++ b/src/process/process_manager.rs
@@ -0,0 +1,494 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+use std::collections::HashMap;
+use std::cmp::Reverse;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::core::syntax::interaction::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::position::*;
+use crate::core::trace::{AnalysableMultiTrace,MultiTraceCanal,TraceAction};
+use crate::process::log::ProcessLogger;
+use crate::core::semantics::frontier::make_frontier;
+use crate::core::semantics::shape_execute::shape_execute;
+use crate::process::verdicts::*;
+use crate::process::hibou_process::*;
+use crate::core::trace::*;
+use crate::process::queue::ProcessQueue;
+
+use crate::process::symbex::model_symbex::*;
+use crate::process::symbex::trace_symbex::*;
+use crate::process::deploy_receptions::deploy_original_action_followup;
+
+use crate::diversity::symbex_client::SymbexClient;
+use crate::diversity::*;
+
+pub struct ProcessPriorities {
+ pub emission : i32,
+ pub reception : i32,
+ pub in_loop : i32
+}
+
+impl ProcessPriorities {
+ pub fn new(emission : i32,
+ reception : i32,
+ in_loop : i32) -> ProcessPriorities {
+ return ProcessPriorities{emission,reception,in_loop};
+ }
+}
+
+impl std::string::ToString for ProcessPriorities {
+ fn to_string(&self) -> String {
+ let mut my_str = format!("emission={:},",self.emission);
+ my_str.push_str( &format!("reception={:},",self.reception));
+ my_str.push_str( &format!("in_loop={:}",self.in_loop));
+ return my_str;
+ }
+}
+
+pub struct HibouProcessManager {
+ gen_ctx : GeneralContext,
+ strategy : HibouSearchStrategy,
+ temporality : HibouProcessTemporality,
+ pre_filters : Vec<HibouPreFilter>,
+ // ***
+ memorized_states : HashMap<u32,MemorizedState>,
+ process_queue : ProcessQueue,
+ // ***
+ frontier_priorities : ProcessPriorities,
+ // ***
+ loggers : Vec<Box<dyn ProcessLogger>>
+}
+
+impl HibouProcessManager {
+ pub fn new(gen_ctx : GeneralContext,
+ strategy : HibouSearchStrategy,
+ temporality : HibouProcessTemporality,
+ pre_filters : Vec<HibouPreFilter>,
+ memorized_states : HashMap<u32,MemorizedState>,
+ process_queue : ProcessQueue,
+ frontier_priorities : ProcessPriorities,
+ loggers : Vec<Box<dyn ProcessLogger>>
+ ) -> HibouProcessManager {
+ return HibouProcessManager{gen_ctx,strategy,temporality,pre_filters,memorized_states,process_queue,frontier_priorities,loggers};
+ }
+
+ pub fn get_options_as_strings(&self,goal_and_verdict:Option<(&GlobalVerdict,&GlobalVerdict)>) -> Vec<String> {
+ let mut options_str : Vec<String> = Vec::new();
+ match goal_and_verdict {
+ None => {
+ options_str.push("process=exploration".to_string());
+ },
+ Some( (goal,verd) ) => {
+ options_str.push("process=analysis".to_string());
+ options_str.push( format!("goal={}", goal.to_string()) );
+ options_str.push( format!("verdict={}", verd.to_string()) );
+ }
+ }
+ options_str.push( format!("temporality={}", &self.temporality.to_string()) );
+ options_str.push( format!("strategy={}", &self.strategy.to_string()) );
+ options_str.push( format!("frontier_priorities=[{}]", &self.frontier_priorities.to_string()) );
+ {
+ let mut rem_filter = self.pre_filters.len();
+ let mut filters_str = "filters=[".to_string();
+ for filter in &self.pre_filters {
+ filters_str.push_str( &filter.to_string() );
+ rem_filter = rem_filter - 1;
+ if rem_filter > 0 {
+ filters_str.push_str( "," );
+ }
+ }
+ filters_str.push_str( "]" );
+ options_str.push( filters_str );
+ }
+ return options_str;
+ }
+
+ pub fn init_loggers(&mut self,
+ exe_ctx : &ExecutionContext,
+ interaction : &Interaction,
+ remaining_multi_trace : &Option<AnalysableMultiTrace>) {
+ for logger in self.loggers.iter_mut() {
+ (*logger).log_init(interaction, &self.gen_ctx, exe_ctx, remaining_multi_trace);
+ }
+ }
+
+ pub fn term_loggers(&mut self,
+ goal_and_verdict:Option<(&GlobalVerdict,&GlobalVerdict)>) {
+ let options_as_strs = (&self).get_options_as_strings(goal_and_verdict);
+ for logger in self.loggers.iter_mut() {
+ (*logger).log_term(&options_as_strs);
+ }
+ }
+
+ pub fn verdict_loggers(&mut self,
+ verdict : &CoverageVerdict,
+ parent_state_id : u32) {
+ for logger in self.loggers.iter_mut() {
+ logger.log_verdict(parent_state_id,
+ verdict);
+ }
+ }
+
+ pub fn filtered_loggers(&mut self,
+ action_position : &Position,
+ executed_action : &ObservableAction,
+ parent_state_id : u32,
+ new_state_id : u32,
+ elim_kind : &FilterEliminationKind) {
+ let parent_state = self.memorized_states.get(&parent_state_id).unwrap();
+ for logger in self.loggers.iter_mut() {
+ logger.log_filtered(&self.gen_ctx,
+ &parent_state.exe_ctx,
+ parent_state_id,
+ new_state_id,
+ action_position,
+ executed_action,
+ elim_kind);
+ }
+ }
+
+ pub fn unsat_loggers(&mut self,
+ action_position : &Position,
+ model_action : &ObservableAction,
+ trace_action : Option<&TraceAction>,
+ parent_state_id : u32,
+ new_state_id : u32) {
+ let parent_state = self.memorized_states.get(&parent_state_id).unwrap();
+ for logger in self.loggers.iter_mut() {
+ logger.log_unsat(&self.gen_ctx,
+ &parent_state.exe_ctx,
+ parent_state_id,
+ new_state_id,
+ action_position,
+ trace_action,
+ model_action);
+ }
+ }
+
+ pub fn execution_loggers(&mut self,
+ action_position : &Position,
+ model_action : &ObservableAction,
+ trace_action : Option<&TraceAction>,
+ new_interaction : &Interaction,
+ new_exe_ctx : &ExecutionContext,
+ parent_state_id : u32,
+ new_state_id :u32,
+ remaining_multi_trace : &Option<AnalysableMultiTrace>) {
+ for logger in self.loggers.iter_mut() {
+ logger.log_execution(&self.gen_ctx,
+ parent_state_id,
+ new_state_id,
+ action_position,
+ trace_action,
+ model_action,
+ new_interaction,
+ new_exe_ctx,
+ remaining_multi_trace);
+ }
+ }
+
+ pub fn get_memorized_state(&self, id:u32) -> Option<&MemorizedState> {
+ return self.memorized_states.get(&id);
+ }
+
+ pub fn forget_state(&mut self, id:u32) {
+ self.memorized_states.remove(&id);
+ }
+
+ pub fn remember_state(&mut self, id:u32, state:MemorizedState) {
+ self.memorized_states.insert( id, state );
+ }
+
+ pub fn extract_from_queue(&mut self) -> Option<NextToProcess> {
+ return self.process_queue.get_next();
+ }
+
+ pub fn enqueue_executions(&mut self, state_id : u32, to_enqueue : Vec<(u32,NextToProcessKind)>) {
+ let mut to_enqueue_reorganize : HashMap<i32,Vec<(u32,NextToProcessKind)>> = HashMap::new();
+ for (child_id,child_kind) in to_enqueue {
+ match &child_kind {
+ &NextToProcessKind::Execute( ref front_pos ) => {
+ let mut priority : i32 = 0;
+ // ***
+ let parent_state = self.get_memorized_state(state_id).unwrap();
+ let front_act = (parent_state.interaction).get_sub_interaction(&front_pos).as_leaf();
+ match front_act.act_kind {
+ ObservableActionKind::Reception => {
+ priority = priority + self.frontier_priorities.reception;
+ },
+ ObservableActionKind::Emission(_) => {
+ priority = priority + self.frontier_priorities.emission;
+ }
+ }
+ let loop_depth = (parent_state.interaction).get_loop_depth_at_pos(&front_pos);
+ if loop_depth > 0 {
+ priority = priority + self.frontier_priorities.in_loop;
+ }
+ // ***
+ match to_enqueue_reorganize.get_mut(&priority) {
+ None => {
+ to_enqueue_reorganize.insert(priority,vec![ (child_id,child_kind) ]);
+ },
+ Some( queue ) => {
+ queue.push((child_id,child_kind) );
+ }
+ }
+ // ***
+ }
+ }
+ }
+ // ***
+ let mut to_enqueue_reorganized : Vec<(u32,NextToProcessKind)> = Vec::new();
+ {
+ let mut keys : Vec<i32> = to_enqueue_reorganize.keys().cloned().collect();
+ keys.sort_by_key(|k| Reverse(*k));
+ for k in keys {
+ match to_enqueue_reorganize.get_mut(&k) {
+ None => {},
+ Some( queue ) => {
+ to_enqueue_reorganized.append( queue );
+ }
+ }
+ }
+ }
+ // ***
+ match &self.strategy {
+ &HibouSearchStrategy::DFS => {
+ to_enqueue_reorganized.reverse();
+ for (child_id,child_kind) in to_enqueue_reorganized {
+ self.enqueue_child_node(state_id,child_id,child_kind);
+ }
+ },
+ &HibouSearchStrategy::BFS => {
+ for (child_id,child_kind) in to_enqueue_reorganized {
+ self.enqueue_child_node(state_id,child_id,child_kind);
+ }
+ }
+ }
+ }
+
+ fn enqueue_child_node(&mut self,state_id: u32,child_id:u32,child_kind:NextToProcessKind) {
+ let child = NextToProcess::new(state_id,child_id,child_kind);
+ match &(self.strategy) {
+ &HibouSearchStrategy::DFS => {
+ self.process_queue.insert_item_left(child);
+ },
+ &HibouSearchStrategy::BFS => {
+ self.process_queue.insert_item_right(child);
+ }
+ }
+ }
+
+ pub async fn process_next(&mut self,
+ client : &mut SymbexClient<tonic::transport::Channel>,
+ parent_state : &MemorizedState,
+ to_process : &NextToProcess,
+ new_state_id : u32,
+ node_counter : u32) -> Option<(Interaction,ExecutionContext,u32,Option<AnalysableMultiTrace>,u32,u32)> {
+ match &(to_process.kind) {
+ &NextToProcessKind::Execute( ref position ) => {
+ let new_depth = parent_state.depth + 1;
+ let new_loop_depth = parent_state.loop_depth + (parent_state.interaction).get_loop_depth_at_pos(position);
+ // ***
+ match self.apply_pre_filters(new_depth,new_loop_depth,node_counter) {
+ None => {
+ let mut new_exe_ctx = parent_state.exe_ctx.clone();
+ match shape_execute(&self.gen_ctx,&mut new_exe_ctx,&parent_state.interaction,position) {
+ Err(e) => {
+ panic!("{:?}",e);
+ },
+ Ok( (shaped_interaction,shaped_position,shaped_action,needs_scoping) ) => {
+ match model_symbolic_execution(client,
+ &self.gen_ctx,
+ &mut new_exe_ctx,
+ &shaped_action,
+ parent_state.diversity_ec_id,
+ needs_scoping,
+ &self.temporality).await {
+ ModelSymbexResult::UnSat => {
+ self.unsat_loggers(&position,
+ &shaped_action,
+ None,
+ to_process.state_id,
+ new_state_id);
+ return None;
+ },
+ ModelSymbexResult::Sat( new_diversity_ec_id,
+ model_firing_conditions,
+ effective_parameters,
+ opt_delay ) => {
+ // ***
+ match (parent_state.multi_trace).as_ref(){
+ None => {
+ let new_interaction = deploy_original_action_followup(&new_exe_ctx,
+ &shaped_interaction,
+ &shaped_position,
+ &shaped_action,
+ &effective_parameters);
+ // ***
+ let trace_act_kind : TraceActionKind;
+ match &shaped_action.act_kind {
+ ObservableActionKind::Reception => {
+ trace_act_kind = TraceActionKind::Reception;
+ },
+ ObservableActionKind::Emission(_) => {
+ trace_act_kind = TraceActionKind::Emission;
+ }
+ }
+ let trace_action = TraceAction{ delay:opt_delay,
+ lf_id:shaped_action.lf_act.lf_id,
+ ms_id:shaped_action.ms_id,
+ act_kind:trace_act_kind,
+ arguments:effective_parameters};
+ // ***
+ self.execution_loggers(&position,
+ &shaped_action,
+ Some(&trace_action),
+ &new_interaction,
+ &new_exe_ctx,
+ to_process.state_id,
+ new_state_id,
+ &None);
+ // ***
+ return Some( (new_interaction,new_exe_ctx,new_diversity_ec_id,None,new_depth,new_loop_depth) );
+ },
+ Some( ref multi_trace ) => {
+ let new_multi_trace : Option<AnalysableMultiTrace>;
+ let mut head_trace_action_opt : Option<TraceAction> = None;
+ {
+ let mut new_canals : Vec<MultiTraceCanal> = Vec::new();
+ for canal in &multi_trace.canals {
+ if canal.lifelines.contains(&shaped_action.occupation_before()) {
+ let mut new_trace = canal.trace.clone();
+ head_trace_action_opt = Some(new_trace.remove(0));
+ new_canals.push( MultiTraceCanal{lifelines:canal.lifelines.clone(),trace:new_trace} )
+ } else {
+ new_canals.push(canal.clone());
+ }
+ }
+ new_multi_trace = Some( AnalysableMultiTrace::new(new_canals) );
+ }
+ let head_trace_action = head_trace_action_opt.unwrap();
+ // ***
+ match trace_symbolic_execution(client,
+ &self.gen_ctx,
+ &mut new_exe_ctx,
+ shaped_action.lf_act.lf_id,
+ shaped_action.ms_id,
+ &head_trace_action.arguments,
+ &head_trace_action.delay,
+ &self.temporality,
+ new_diversity_ec_id).await {
+ TraceSymbexResult::UnSat(trace_firing_conditions) => {
+ self.unsat_loggers(&position,
+ &shaped_action,
+ Some(&head_trace_action),
+ to_process.state_id,
+ new_state_id);
+ return None;
+ },
+ TraceSymbexResult::Sat(post_trace_analysis_diversity_ec_id,trace_firing_condition) => {
+ let post_trace_analysis_interaction = deploy_original_action_followup(&new_exe_ctx,
+ &shaped_interaction,
+ &shaped_position,
+ &shaped_action,
+ &head_trace_action.arguments);
+ // ***
+ self.execution_loggers(&position,
+ &shaped_action,
+ Some(&head_trace_action),
+ &post_trace_analysis_interaction,
+ &new_exe_ctx,
+ to_process.state_id,
+ new_state_id,
+ &new_multi_trace);
+ // ***
+ return Some( (post_trace_analysis_interaction,
+ new_exe_ctx,
+ post_trace_analysis_diversity_ec_id,
+ new_multi_trace,
+ new_depth,
+ new_loop_depth) );
+ }
+ }
+ // ***
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ Some( elim_kind ) => {
+ let executed_action = (parent_state.interaction).get_sub_interaction(position).as_leaf();
+ self.filtered_loggers(&position,
+ executed_action,
+ to_process.state_id,
+ new_state_id,
+ &elim_kind);
+ return None;
+ }
+ }
+ },
+ _ => {
+ return None;
+ }
+ }
+ }
+
+ fn apply_pre_filters(&self, depth : u32, loop_depth : u32, node_counter : u32) -> Option<FilterEliminationKind> {
+ for pre_filter in &self.pre_filters {
+ match pre_filter {
+ HibouPreFilter::MaxProcessDepth( max_depth ) => {
+ if depth > *max_depth {
+ return Some( FilterEliminationKind::MaxProcessDepth );
+ }
+ },
+ HibouPreFilter::MaxLoopInstanciation( loop_num ) => {
+ if loop_depth > *loop_num {
+ return Some( FilterEliminationKind::MaxLoopInstanciation );
+ }
+ },
+ HibouPreFilter::MaxNodeNumber( max_node_number ) => {
+ if node_counter >= *max_node_number {
+ return Some( FilterEliminationKind::MaxNodeNumber );
+ }
+ }
+ }
+ }
+ return None;
+ }
+
+ pub fn get_coverage_verdict(&self,interaction:&Interaction,multi_trace:&AnalysableMultiTrace) -> CoverageVerdict {
+ if multi_trace.length() == 0 {
+ if interaction.express_empty() {
+ return CoverageVerdict::Cov;
+ } else {
+ return CoverageVerdict::TooShort;
+ }
+ } else {
+ if multi_trace.is_any_component_empty() {
+ return CoverageVerdict::LackObs;
+ } else {
+ return CoverageVerdict::Out;
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/process/queue.rs b/src/process/queue.rs
new file mode 100644
index 0000000..0d0e0dd
--- /dev/null
+++ b/src/process/queue.rs
@@ -0,0 +1,43 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use crate::process::hibou_process::NextToProcess;
+
+
+pub struct ProcessQueue {
+ queue : Vec<NextToProcess>
+}
+
+impl ProcessQueue {
+ pub fn new() -> ProcessQueue {
+ return ProcessQueue{queue:Vec::new()}
+ }
+
+ pub fn insert_item_left(&mut self,node:NextToProcess) {
+ self.queue.insert(0,node);
+ }
+
+ pub fn insert_item_right(&mut self,node:NextToProcess) {
+ self.queue.push(node);
+ }
+
+ pub fn get_next(&mut self) -> Option<NextToProcess> {
+ if self.queue.len() > 0 {
+ return Some( self.queue.remove(0) );
+ } else {
+ return None;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/process/symbex/mod.rs b/src/process/symbex/mod.rs
new file mode 100644
index 0000000..fce42a1
--- /dev/null
+++ b/src/process/symbex/mod.rs
@@ -0,0 +1,16 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod model_symbex;
+pub mod trace_symbex;
\ No newline at end of file
diff --git a/src/process/symbex/model_symbex.rs b/src/process/symbex/model_symbex.rs
new file mode 100644
index 0000000..ac71a9b
--- /dev/null
+++ b/src/process/symbex/model_symbex.rs
@@ -0,0 +1,263 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::BTreeMap;
+use std::collections::{HashSet,HashMap};
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::interaction::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::position::*;
+use crate::core::trace::*;
+use crate::process::log::ProcessLogger;
+use crate::core::semantics::frontier::make_frontier;
+
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::core::syntax::data::builtin::float::TD_Float;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::td_type::TD_DataType;
+
+use crate::process::hibou_process::*;
+
+use crate::grpc_connect::calls::*;
+use crate::xlia::model::generate_xlia_model;
+
+use crate::diversity::symbex_client::SymbexClient;
+use crate::diversity::*;
+
+use crate::core::semantics::shape_execute::shape_execute;
+
+use crate::grpc_connect::to_grpc::{td_generic_to_grpc,td_bool_to_grpc};
+
+use crate::grpc_connect::xlia_reference_name_tools::*;
+use crate::process::deploy_receptions::deploy_original_action_followup;
+
+
+
+
+pub enum ModelSymbexResult {
+ Sat(u32,TD_Bool,Vec<TD_Generic>,Option<TD_Float>), //new_ec_id,model_firing_condition,effective_parameters,delay
+ UnSat //(HibouExecutionFailure)
+}
+
+pub async fn model_symbolic_execution( client : &mut SymbexClient<tonic::transport::Channel>,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &mut ExecutionContext,
+ model_action : &ObservableAction,
+ parent_diversity_ec_id : u32,
+ needs_scoping : bool,
+ temporality : &HibouProcessTemporality)
+ -> ModelSymbexResult {
+ // ***
+ let appearing_variables : HashSet<usize> = gather_appearing_variables(model_action);
+ // ***
+ let mut variable_diversity_values : Vec<VariableValuePair> = Vec::new();
+ for vr_id in &appearing_variables {
+ let (_,meta_var_idx) = exe_ctx.get_vr_parent_name_and_child_id(gen_ctx,*vr_id).unwrap();
+ let varindex_fqn = varindex_diversity_fqn(gen_ctx,exe_ctx, model_action.lf_act.lf_id,*vr_id);
+ let td_gen = TD_Generic::Integer(TD_Integer::Value(meta_var_idx as i64));
+ variable_diversity_values.push( VariableValuePair{variable_id:varindex_fqn,
+ value : Some(td_generic_to_grpc(gen_ctx,exe_ctx,model_action.lf_act.lf_id,&td_gen))} );
+ }
+ // ***
+ match model_action.act_kind {
+ /*
+ In case of a reception,
+ the values must be provided to DIVERSITY by HIBOU
+ */
+ ObservableActionKind::Reception => {
+ let mut pr_id : usize = 0;
+ for param in &model_action.params {
+ match param {
+ ValueOrNewFresh::Value(td_gen) => {
+ let param_diversity_fqn = message_parameter_diversity_fqn(gen_ctx,exe_ctx,model_action.lf_act.lf_id,model_action.ms_id,pr_id);
+ variable_diversity_values.push( VariableValuePair{variable_id:param_diversity_fqn,
+ value : Some(td_generic_to_grpc(gen_ctx,exe_ctx,model_action.lf_act.lf_id,&td_gen))} );
+ },
+ ValueOrNewFresh::NewFresh => {
+ // do nothing
+ }
+ }
+ pr_id = pr_id + 1;
+ }
+ },
+ /*
+ In case of an emission,
+ DIVERSITY will write the new values on the emitting lifeline's message parameters variables
+ */
+ _ => {}
+ }
+ // ***
+ let current_diversity_ec_id : u32;
+ if needs_scoping {
+ current_diversity_ec_id = symbex_open_scopes(client, gen_ctx, exe_ctx,parent_diversity_ec_id).await;
+ } else {
+ current_diversity_ec_id = parent_diversity_ec_id;
+ }
+ // ***
+ let target_action_fqn = action_diversity_fqn(gen_ctx,exe_ctx,model_action.lf_act.lf_id,(model_action.original_position).as_ref().unwrap() );
+ match symbex_fire_action(gen_ctx,
+ exe_ctx,
+ current_diversity_ec_id,
+ client,
+ target_action_fqn,
+ variable_diversity_values).await {
+ SymbexResult::UnSAT => {
+ /*let fail_kind = HibouExecutionFailure::SolverUnSat(exe_ctx.clone(),
+ model_action.clone(),
+ None,
+ TD_Bool::FALSE,
+ None);*/
+ return ModelSymbexResult::UnSat; //(fail_kind);
+ },
+ SymbexResult::Success( symbex_result ) => {
+ // ***
+ let mut lf_interpretation : BTreeMap<usize,TD_Generic>;
+ match exe_ctx.get_lf_interpretation(model_action.lf_act.lf_id) {
+ None => {
+ lf_interpretation = BTreeMap::new();
+ },
+ Some( got_lfint ) => {
+ lf_interpretation = got_lfint.clone();
+ }
+ }
+ // ***
+ {
+ let mut variables_to_query_values: HashSet<usize> = appearing_variables.clone(); //.union(exe_ctx.get_active_clocks()).cloned().collect();
+ for clock_id in exe_ctx.get_active_clocks() {
+ if lf_interpretation.contains_key(clock_id) {
+ variables_to_query_values.insert(*clock_id);
+ }
+ }
+ // ***
+ for vr_id in &variables_to_query_values {
+ let vr_type = exe_ctx.get_vr_type(gen_ctx,*vr_id).unwrap();
+ let var_fqn = variable_diversity_fqn(gen_ctx,exe_ctx,model_action.lf_act.lf_id,*vr_id);
+ println!("HIBOU requested value of variable '{:?}' to DIVERSITY...",var_fqn);
+ let td_gen = symbex_request_variable(gen_ctx,exe_ctx,symbex_result.new_diversity_ec_id,client,var_fqn,&vr_type).await;
+ println!("...DIVERSITY provided value '{:?}'...",td_gen);
+ lf_interpretation.insert(*vr_id,td_gen);
+ println!("...updated in HIBOU intrepretation");
+ }
+ }
+ // ***
+ exe_ctx.set_lf_interpretation(model_action.lf_act.lf_id,lf_interpretation);
+
+ /*
+ HIBOU queries DIVERSITY
+ for the values of the message parameters
+ */
+ let mut effective_parameters : Vec<TD_Generic> = Vec::new();
+ let mut pr_id : usize = 0;
+ for param in &model_action.params {
+ let prm_type = gen_ctx.get_pr_type(model_action.ms_id, pr_id).unwrap();
+ let prm_fqn = message_parameter_diversity_fqn(gen_ctx,exe_ctx,model_action.lf_act.lf_id,model_action.ms_id,pr_id);
+ let td_gen = symbex_request_variable(gen_ctx,exe_ctx,symbex_result.new_diversity_ec_id,client,prm_fqn,&prm_type).await;
+ effective_parameters.push( td_gen );
+ pr_id = pr_id +1;
+ }
+ // ***
+ match temporality {
+ HibouProcessTemporality::UnTimed => {
+ return ModelSymbexResult::Sat( symbex_result.new_diversity_ec_id,
+ symbex_result.firing_condition,
+ effective_parameters,
+ None );
+ },
+ HibouProcessTemporality::Timed => {
+ println!("HIBOU requested delay symbol to DIVERSITY...");
+ let td_gen = symbex_request_variable(gen_ctx,exe_ctx,symbex_result.new_diversity_ec_id,client,"$delay".to_string(),&TD_DataType::Float).await;
+ println!("...DIVERSITY provided value '{:?}'...",td_gen);
+ match td_gen {
+ TD_Generic::Float(td_float) => {
+ return ModelSymbexResult::Sat( symbex_result.new_diversity_ec_id,
+ symbex_result.firing_condition,
+ effective_parameters,
+ Some(td_float) );
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+ }
+
+ }
+ }
+}
+
+
+fn gather_appearing_variables(model_action : &ObservableAction) -> HashSet<usize> {
+ let mut appearing_variables : HashSet<usize> = HashSet::new();
+ // ***
+ for amble_item in &model_action.lf_act.preamble {
+ match amble_item {
+ ActionAmbleItem::Guard(td_bool) => {
+ appearing_variables.extend(td_bool.get_occuring_variables() );
+ },
+ ActionAmbleItem::Assignment( var_id, value_or_new_fresh) => {
+ appearing_variables.insert( *var_id );
+ match value_or_new_fresh {
+ ValueOrNewFresh::Value( td_gen ) => {
+ appearing_variables.extend(td_gen.get_occuring_variables() );
+ },
+ _ => {}
+ }
+ },
+ ActionAmbleItem::Reset( var_id ) => {
+ appearing_variables.insert( *var_id );
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+ // ***
+ for value_or_new_fresh in &model_action.params {
+ match value_or_new_fresh {
+ ValueOrNewFresh::Value( ref td_gen ) => {
+ appearing_variables.extend(td_gen.get_occuring_variables() );
+ },
+ _ => {}
+ }
+ }
+ // ***
+ for amble_item in &model_action.lf_act.postamble {
+ match amble_item {
+ ActionAmbleItem::Guard(td_bool) => {
+ appearing_variables.extend(td_bool.get_occuring_variables() );
+ },
+ ActionAmbleItem::Assignment( var_id, value_or_new_fresh) => {
+ appearing_variables.insert( *var_id );
+ match value_or_new_fresh {
+ ValueOrNewFresh::Value( td_gen ) => {
+ appearing_variables.extend(td_gen.get_occuring_variables() );
+ },
+ _ => {}
+ }
+ },
+ ActionAmbleItem::Reset( var_id ) => {
+ appearing_variables.insert( *var_id );
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+ return appearing_variables;
+}
+
+
diff --git a/src/process/symbex/trace_symbex.rs b/src/process/symbex/trace_symbex.rs
new file mode 100644
index 0000000..107cf66
--- /dev/null
+++ b/src/process/symbex/trace_symbex.rs
@@ -0,0 +1,110 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::BTreeMap;
+use std::collections::{HashSet,HashMap};
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::interaction::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::position::*;
+use crate::core::trace::*;
+use crate::process::log::ProcessLogger;
+use crate::core::semantics::frontier::make_frontier;
+
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::core::syntax::data::builtin::float::TD_Float;
+use crate::core::syntax::data::generic::TD_Generic;
+
+use crate::process::hibou_process::*;
+
+use crate::xlia::model::generate_xlia_model;
+
+use crate::grpc_connect::calls::*;
+
+use crate::diversity::symbex_client::SymbexClient;
+use crate::diversity::*;
+
+use crate::core::semantics::shape_execute::shape_execute;
+
+use crate::grpc_connect::to_grpc::{td_generic_to_grpc,td_bool_to_grpc};
+
+use crate::grpc_connect::xlia_reference_name_tools::*;
+use crate::process::deploy_receptions::deploy_original_action_followup;
+
+
+
+
+pub enum TraceSymbexResult {
+ Sat(u32,TD_Bool), //new_ec_id,trace_firing_condition
+ UnSat(TD_Bool) // trace_firing_condition
+}
+
+pub async fn trace_symbolic_execution( client : &mut SymbexClient<tonic::transport::Channel>,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &mut ExecutionContext,
+ lf_id : usize,
+ ms_id : usize,
+ trace_params : &Vec<TD_Generic>,
+ trace_delay_opt : &Option<TD_Float>,
+ temporality : &HibouProcessTemporality,
+ parent_diversity_ec_id : u32)
+ -> TraceSymbexResult {
+ // ***
+ let mut param_counter : usize = 0;
+ let mut variable_diversity_values : Vec<VariableValuePair> = Vec::new();
+ for trace_param_td_gen in trace_params {
+ let trace_param_diversity_fqn = trace_message_parameter_diversity_fqn(gen_ctx,exe_ctx,lf_id,ms_id,param_counter);
+ variable_diversity_values.push( VariableValuePair{variable_id:trace_param_diversity_fqn,
+ value : Some(td_generic_to_grpc(gen_ctx,exe_ctx,lf_id,trace_param_td_gen))} );
+ param_counter = param_counter +1;
+ }
+ // ***
+ match temporality {
+ HibouProcessTemporality::UnTimed => {
+ // nothing
+ },
+ HibouProcessTemporality::Timed => {
+ match trace_delay_opt {
+ None => {
+ panic!();
+ },
+ Some( delay_td_float ) => {
+ let trace_delay_fqn = trace_delay_diversity_fqn(gen_ctx,exe_ctx,lf_id);
+ variable_diversity_values.push( VariableValuePair{variable_id:trace_delay_fqn,
+ value : Some(td_generic_to_grpc(gen_ctx,exe_ctx,lf_id,&TD_Generic::Float(delay_td_float.clone())))} );
+ }
+ }
+ }
+ }
+ // ***
+ let target_action_fqn = trace_action_compare_diversity_fqn(gen_ctx,exe_ctx,lf_id,ms_id);
+ match symbex_fire_action(gen_ctx,
+ exe_ctx,
+ parent_diversity_ec_id,
+ client,
+ target_action_fqn,
+ variable_diversity_values).await {
+ SymbexResult::UnSAT => {
+ return TraceSymbexResult::UnSat( TD_Bool::FALSE );
+ },
+ SymbexResult::Success( symbex_result ) => {
+ return TraceSymbexResult::Sat( symbex_result.new_diversity_ec_id,
+ symbex_result.firing_condition);
+ }
+ }
+}
+
diff --git a/src/process/verdicts.rs b/src/process/verdicts.rs
new file mode 100644
index 0000000..761a67a
--- /dev/null
+++ b/src/process/verdicts.rs
@@ -0,0 +1,116 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+pub enum CoverageVerdict{
+ Cov,
+ TooShort,
+ LackObs,
+ Out
+}
+
+impl std::string::ToString for CoverageVerdict {
+
+ fn to_string(&self) -> String {
+ match self {
+ CoverageVerdict::Cov => {
+ return "Cov".to_string();
+ },
+ CoverageVerdict::TooShort => {
+ return "TooShort".to_string();
+ },
+ CoverageVerdict::LackObs => {
+ return "LackObs".to_string();
+ },
+ CoverageVerdict::Out => {
+ return "Out".to_string();
+ }
+ }
+ }
+
+}
+
+#[derive(PartialEq, Eq, PartialOrd, Ord)]
+pub enum GlobalVerdict {
+ Fail,
+ Inconc,
+ WeakPass,
+ Pass
+}
+
+impl std::string::ToString for GlobalVerdict {
+ fn to_string(&self) -> String {
+ match self {
+ GlobalVerdict::Pass => {
+ return "Pass".to_string();
+ },
+ GlobalVerdict::WeakPass => {
+ return "WeakPass".to_string();
+ },
+ GlobalVerdict::Inconc => {
+ return "Inconc".to_string();
+ },
+ GlobalVerdict::Fail => {
+ return "Fail".to_string();
+ }
+ }
+ }
+}
+
+pub fn update_global_verdict_from_new_coverage_verdict(glo:GlobalVerdict,cov:CoverageVerdict) -> GlobalVerdict {
+ match glo {
+ GlobalVerdict::Pass => {
+ return GlobalVerdict::Pass;
+ },
+ GlobalVerdict::WeakPass => {
+ match cov {
+ CoverageVerdict::Cov => {
+ return GlobalVerdict::Pass;
+ },
+ _ => {
+ return GlobalVerdict::WeakPass;
+ }
+ }
+ },
+ GlobalVerdict::Inconc => {
+ match cov {
+ CoverageVerdict::Cov => {
+ return GlobalVerdict::Pass;
+ },
+ CoverageVerdict::TooShort => {
+ return GlobalVerdict::WeakPass;
+ },
+ _ => {
+ return GlobalVerdict::Inconc;
+ }
+ }
+ },
+ GlobalVerdict::Fail => {
+ match cov {
+ CoverageVerdict::Cov => {
+ return GlobalVerdict::Pass;
+ },
+ CoverageVerdict::TooShort => {
+ return GlobalVerdict::WeakPass;
+ },
+ CoverageVerdict::LackObs => {
+ return GlobalVerdict::Inconc;
+ },
+ _ => {
+ return GlobalVerdict::Fail;
+ }
+ }
+ }
+ }
+}
diff --git a/src/rendering/DejaVuFontsLicense.txt b/src/rendering/DejaVuFontsLicense.txt
new file mode 100644
index 0000000..6939980
--- /dev/null
+++ b/src/rendering/DejaVuFontsLicense.txt
@@ -0,0 +1,97 @@
+Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
+Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
+
+Bitstream Vera Fonts Copyright
+------------------------------
+
+Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
+a trademark of Bitstream, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of the fonts accompanying this license ("Fonts") and associated
+documentation files (the "Font Software"), to reproduce and distribute the
+Font Software, including without limitation the rights to use, copy, merge,
+publish, distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright and trademark notices and this permission notice shall
+be included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular
+the designs of glyphs or characters in the Fonts may be modified and
+additional glyphs or characters may be added to the Fonts, only if the fonts
+are renamed to names not containing either the words "Bitstream" or the word
+"Vera".
+
+This License becomes null and void to the extent applicable to Fonts or Font
+Software that has been modified and is distributed under the "Bitstream
+Vera" names.
+
+The Font Software may be sold as part of a larger software package but no
+copy of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
+TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
+FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
+ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
+FONT SOFTWARE.
+
+Except as contained in this notice, the names of Gnome, the Gnome
+Foundation, and Bitstream Inc., shall not be used in advertising or
+otherwise to promote the sale, use or other dealings in this Font Software
+without prior written authorization from the Gnome Foundation or Bitstream
+Inc., respectively. For further information, contact: fonts at gnome dot
+org.
+
+Arev Fonts Copyright
+------------------------------
+
+Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the fonts accompanying this license ("Fonts") and
+associated documentation files (the "Font Software"), to reproduce
+and distribute the modifications to the Bitstream Vera Font Software,
+including without limitation the rights to use, copy, merge, publish,
+distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright and trademark notices and this permission notice
+shall be included in all copies of one or more of the Font Software
+typefaces.
+
+The Font Software may be modified, altered, or added to, and in
+particular the designs of glyphs or characters in the Fonts may be
+modified and additional glyphs or characters may be added to the
+Fonts, only if the fonts are renamed to names not containing either
+the words "Tavmjong Bah" or the word "Arev".
+
+This License becomes null and void to the extent applicable to Fonts
+or Font Software that has been modified and is distributed under the
+"Tavmjong Bah Arev" names.
+
+The Font Software may be sold as part of a larger software package but
+no copy of one or more of the Font Software typefaces may be sold by
+itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
+TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
+
+Except as contained in this notice, the name of Tavmjong Bah shall not
+be used in advertising or otherwise to promote the sale, use or other
+dealings in this Font Software without prior written authorization
+from Tavmjong Bah. For further information, contact: tavmjong @ free
+. fr.
\ No newline at end of file
diff --git a/src/rendering/DejaVuSansMono.ttf b/src/rendering/DejaVuSansMono.ttf
new file mode 100644
index 0000000..8b7bb2a
--- /dev/null
+++ b/src/rendering/DejaVuSansMono.ttf
Binary files differ
diff --git a/src/rendering/custom_draw/extraction/ext_context.rs b/src/rendering/custom_draw/extraction/ext_context.rs
new file mode 100644
index 0000000..7391571
--- /dev/null
+++ b/src/rendering/custom_draw/extraction/ext_context.rs
@@ -0,0 +1,54 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::cmp;
+use std::collections::HashMap;
+use std::collections::btree_map::BTreeMap;
+use image::Rgb;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::textual::colored::amble::diagram_revr_amble;
+use crate::rendering::textual::colored::message::diagram_repr_message;
+use crate::rendering::hibou_color_palette::*;
+
+
+pub fn extract_texts_on_interpretation(gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext) -> HashMap< usize,(usize,Vec<Vec<TextToPrint>>) > {
+ let mut lfs_extractions : HashMap< usize,(usize,Vec<Vec<TextToPrint>>) > = HashMap::new();
+ for lf_id in 0..gen_ctx.get_lf_num() {
+ match exe_ctx.get_lf_interpretation(lf_id) {
+ None => {},
+ Some( lf_interpretation ) => {
+ let mut init_texts_vec : Vec<Vec<TextToPrint>> = Vec::new();
+ let mut max_text_size = 0;
+ for (vr_id,td_generic) in lf_interpretation {
+ let mut to_print : Vec<TextToPrint> = Vec::new();
+ let vr_name = exe_ctx.get_vr_name(gen_ctx,*vr_id).unwrap();
+ to_print.push( TextToPrint{text:vr_name,color:Rgb(HC_Variable)});
+ to_print.push( TextToPrint{text:"=".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ to_print.append( &mut td_generic.to_colored_text(gen_ctx,exe_ctx));
+ max_text_size = cmp::max(max_text_size, TextToPrint::char_count(&to_print));
+ init_texts_vec.push(to_print );
+ }
+ if init_texts_vec.len() > 0 {
+ lfs_extractions.insert(lf_id, (max_text_size,init_texts_vec));
+ }
+ }
+ }
+ }
+ return lfs_extractions;
+}
\ No newline at end of file
diff --git a/src/rendering/custom_draw/extraction/ext_interaction.rs b/src/rendering/custom_draw/extraction/ext_interaction.rs
new file mode 100644
index 0000000..5217be9
--- /dev/null
+++ b/src/rendering/custom_draw/extraction/ext_interaction.rs
@@ -0,0 +1,161 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::cmp;
+use std::collections::HashMap;
+use image::Rgb;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::interaction::Interaction;
+use crate::core::syntax::action::*;
+
+use crate::core::syntax::position::{Position,SYNTAX_POSITION_EPSILON,SYNTAX_POSITION_LEFT,SYNTAX_POSITION_RIGHT};
+use crate::rendering::textual::colored::colored_text::TextToPrint;
+use crate::rendering::textual::colored::amble::diagram_revr_amble;
+use crate::rendering::textual::colored::message::diagram_repr_message;
+use crate::rendering::hibou_color_palette::*;
+
+pub fn extract_texts_on_interaction(interaction : &Interaction,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext) -> (HashMap<usize,usize>,Vec<Vec<TextToPrint>>) {
+ match interaction {
+ Interaction::Empty => {
+ return (HashMap::new(),Vec::new());
+ },
+ Interaction::Action( act ) => {
+ // ***
+ let mut lf_char_spaces : HashMap<usize,usize> = HashMap::new();
+ let mut texts : Vec<Vec<TextToPrint>> = Vec::new();
+ // ***
+ let msg_to_print = diagram_repr_message(act.ms_id,&act.params,gen_ctx,exe_ctx);
+ match lf_char_spaces.get(&act.lf_act.lf_id) {
+ None => {
+ lf_char_spaces.insert(*(&act.lf_act.lf_id),TextToPrint::char_count(&msg_to_print));
+ },
+ Some( current_max_char ) => {
+ lf_char_spaces.insert(*(&act.lf_act.lf_id),cmp::max(*current_max_char,TextToPrint::char_count(&msg_to_print)));
+ }
+ }
+ texts.push( msg_to_print );
+ // ***
+ {
+ let (main_lf_chars, mut main_lf_to_print) = extract_texts_on_pre_post_amble(&act.lf_act.preamble, &act.lf_act.postamble, gen_ctx, exe_ctx);
+ match lf_char_spaces.get(&act.lf_act.lf_id) {
+ None => {
+ lf_char_spaces.insert(*(&act.lf_act.lf_id),main_lf_chars);
+ },
+ Some( current_max_char ) => {
+ lf_char_spaces.insert(*(&act.lf_act.lf_id),cmp::max(*current_max_char,main_lf_chars ));
+ }
+ }
+ texts.append(&mut main_lf_to_print);
+ }
+ // ***
+ match &act.act_kind {
+ ObservableActionKind::Reception => {},
+ ObservableActionKind::Emission( targets ) => {
+ for tar_lf_act in targets {
+ let (tar_lf_chars, mut tar_lf_to_print) = extract_texts_on_pre_post_amble(&tar_lf_act.preamble, &tar_lf_act.postamble,gen_ctx,exe_ctx);
+ match lf_char_spaces.get(&tar_lf_act.lf_id) {
+ None => {
+ lf_char_spaces.insert(tar_lf_act.lf_id,tar_lf_chars);
+ },
+ Some( current_max_char ) => {
+ lf_char_spaces.insert(tar_lf_act.lf_id,cmp::max(*current_max_char,tar_lf_chars));
+ }
+ }
+ texts.append(&mut tar_lf_to_print);
+ }
+ }
+ }
+ // ***
+ return (lf_char_spaces,texts);
+ },
+ Interaction::Strict(i1,i2) => {
+ //let (height,lf_widths,texts) = extract_texts_in_binary_operator(i1,i2,gen_ctx,exe_ctx);
+ return extract_texts_in_binary_operator(i1,i2,gen_ctx,exe_ctx);
+ },
+ Interaction::Seq(i1,i2) => {
+ return extract_texts_in_binary_operator(i1,i2,gen_ctx,exe_ctx);
+ },
+ Interaction::Alt(i1,i2) => {
+ return extract_texts_in_binary_operator(i1,i2,gen_ctx,exe_ctx);
+ },
+ Interaction::Par(i1,i2) => {
+ return extract_texts_in_binary_operator(i1,i2,gen_ctx,exe_ctx);
+ },
+ Interaction::Loop(_,i1) => {
+ return extract_texts_on_interaction(i1,gen_ctx,exe_ctx);
+ },
+ Interaction::Scope(vr_ids_vec,i1) => {
+ let mut scope_text : Vec<TextToPrint> = Vec::new();
+ let mut counter : usize = 0;
+ for vr_id in vr_ids_vec {
+ let vr_label: String = exe_ctx.get_vr_name(gen_ctx,*vr_id).unwrap();
+ scope_text.push( TextToPrint{text:vr_label,color:Rgb(HC_Variable)} );
+ counter = counter +1;
+ if counter < vr_ids_vec.len() {
+ scope_text.push( TextToPrint{text:",".to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ }
+ }
+ let (inner_space,mut inner_texts) = extract_texts_on_interaction(i1,gen_ctx,exe_ctx);
+ let mut texts : Vec<Vec<TextToPrint>> = Vec::new();
+ texts.push(scope_text);
+ texts.append( &mut inner_texts);
+ return (inner_space,texts);
+ }
+ }
+}
+
+fn extract_texts_in_binary_operator(i1:&Interaction,i2:&Interaction,gen_ctx:&GeneralContext,exe_ctx:&ExecutionContext) -> (HashMap<usize,usize>,Vec<Vec<TextToPrint>>) {
+ let (mut i1_spaces,mut i1_texts) = extract_texts_on_interaction(i1,gen_ctx,exe_ctx);
+ let (i2_spaces,mut i2_texts) = extract_texts_on_interaction(i2,gen_ctx,exe_ctx);
+ // ***
+ for (lf_id,space) in i2_spaces.iter() {
+ match i1_spaces.get(lf_id) {
+ None => {
+ i1_spaces.insert( *lf_id, *space);
+ },
+ Some( other_space ) => {
+ i1_spaces.insert( *lf_id, cmp::max(*space,*other_space));
+ }
+ }
+ }
+ // ***
+ i1_texts.append(&mut i2_texts);
+ return (i1_spaces,i1_texts);
+}
+
+fn extract_texts_on_pre_post_amble(preamble : &Vec<ActionAmbleItem>,
+ postamble : &Vec<ActionAmbleItem>,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext) -> (usize,Vec<Vec<TextToPrint>>) {
+ let mut max_on_lf : usize = 1; // min 1 because lf appears
+ let mut to_print : Vec<Vec<TextToPrint>> = Vec::new();
+ // ***
+ let preamble_texts = diagram_revr_amble(preamble,gen_ctx,exe_ctx);
+ for am_item_txt in preamble_texts {
+ max_on_lf = cmp::max(max_on_lf, TextToPrint::char_count(&am_item_txt));
+ to_print.push(am_item_txt);
+ }
+ // ***
+ let postamble_texts = diagram_revr_amble(postamble,gen_ctx,exe_ctx);
+ for am_item_txt in postamble_texts {
+ max_on_lf = cmp::max(max_on_lf, TextToPrint::char_count(&am_item_txt));
+ to_print.push(am_item_txt);
+ }
+ // ***
+ return (max_on_lf,to_print);
+}
\ No newline at end of file
diff --git a/src/rendering/custom_draw/extraction/ext_multi_trace.rs b/src/rendering/custom_draw/extraction/ext_multi_trace.rs
new file mode 100644
index 0000000..885338e
--- /dev/null
+++ b/src/rendering/custom_draw/extraction/ext_multi_trace.rs
@@ -0,0 +1,70 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+use std::cmp;
+use std::collections::HashMap;
+use image::Rgb;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::trace::{MultiTraceCanal,AnalysableMultiTrace,TraceAction,TraceActionKind};
+
+use crate::rendering::textual::colored::colored_text::TextToPrint;
+use crate::rendering::textual::colored::short_action::diagram_repr_atomic_trace_action;
+use crate::rendering::hibou_color_palette::*;
+
+pub fn extract_texts_on_multi_trace(gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ multi_trace : &AnalysableMultiTrace) -> Vec<Vec<TextToPrint>> {
+ let mut all_texts : Vec<Vec<TextToPrint>> = Vec::new();
+ for trace_canal in &multi_trace.canals {
+ let mut canal_text : Vec<TextToPrint> = Vec::new();
+ // ***
+ canal_text.push( TextToPrint{text:"[".to_string(), color:Rgb(HC_Grammar_Symbol)} );
+ let mut remaining_len = trace_canal.lifelines.len();
+ for lf_id in &trace_canal.lifelines {
+ let lf_name = gen_ctx.get_lf_name(*lf_id).unwrap();
+ canal_text.push( TextToPrint{text:lf_name, color:Rgb(HC_Lifeline)} );
+ remaining_len = remaining_len -1;
+ if remaining_len > 0 {
+ canal_text.push( TextToPrint{text:",".to_string(), color:Rgb(HC_Grammar_Symbol)} );
+ }
+ }
+ canal_text.push( TextToPrint{text:"] ".to_string(), color:Rgb(HC_Grammar_Symbol)} );
+ // ***
+ let canal_len = trace_canal.trace.len();
+ if canal_len > 0 {
+ let first_act: &TraceAction = trace_canal.trace.get(0).unwrap();
+ canal_text.append(&mut diagram_repr_atomic_trace_action(first_act, gen_ctx, exe_ctx) );
+ if canal_len > 1 {
+ canal_text.push( TextToPrint{text:format!("...+{:}",(canal_len-1)), color:Rgb(HC_Grammar_Symbol)} );
+ }
+ /*
+ let mut remaining = canal_len;
+ for act in &(trace_canal.trace) {
+ canal_text.append(&mut diagram_repr_atomic_trace_action(act, gen_ctx, exe_ctx) );
+ remaining = remaining -1;
+ if remaining > 0 {
+ canal_text.push( TextToPrint{text:".".to_string(), color:Rgb(HC_Grammar_Symbol)} );
+ }
+ }*/
+ } else {
+ canal_text.push( TextToPrint{text:"o".to_string(), color:Rgb(HCP_LightGray)} );
+ }
+ canal_text.push( TextToPrint{text:" ".to_string(), color:Rgb(HCP_Black)} );
+ all_texts.push(canal_text);
+ }
+ return all_texts;
+}
diff --git a/src/rendering/custom_draw/extraction/mod.rs b/src/rendering/custom_draw/extraction/mod.rs
new file mode 100644
index 0000000..b0d13cc
--- /dev/null
+++ b/src/rendering/custom_draw/extraction/mod.rs
@@ -0,0 +1,17 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod ext_interaction;
+pub mod ext_context;
+pub mod ext_multi_trace;
\ No newline at end of file
diff --git a/src/rendering/custom_draw/firing/draw_firing.rs b/src/rendering/custom_draw/firing/draw_firing.rs
new file mode 100644
index 0000000..85074a0
--- /dev/null
+++ b/src/rendering/custom_draw/firing/draw_firing.rs
@@ -0,0 +1,140 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashSet;
+use std::cmp;
+use std::path::Path;
+use std::collections::HashMap;
+
+// **********
+
+use image::{Rgb, RgbImage};
+use imageproc::rect::Rect;
+use imageproc::drawing::{
+ Point,
+ draw_cross_mut,
+ draw_line_segment_mut,
+ draw_hollow_rect_mut,
+ draw_filled_rect_mut,
+ draw_hollow_circle_mut,
+ draw_filled_circle_mut,
+ draw_convex_polygon_mut,
+ draw_text_mut
+};
+// **********
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::interaction::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::position::*;
+
+use crate::rendering::sd_drawing_conf::*;
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::textual::colored::short_action::{diagram_repr_atomic_model_action,diagram_repr_atomic_trace_action};
+
+use crate::rendering::hibou_color_palette::*;
+use crate::rendering::textual::monochrome::position::position_to_text;
+use crate::rendering::custom_draw::utils::colored_text::draw_colored_text;
+
+use crate::core::trace::{TraceAction,TraceActionKind};
+// **********
+
+
+
+/*
+pub fn draw_firing_on_trace_action(path_str : &String,
+ action_position : &Position,
+ action : &TraceAction,
+ gen_ctx : &GeneralContext,
+ exe_ctx:&ExecutionContext) {
+ let mut ttp = diagram_repr_atomic_trace_action(action,gen_ctx,exe_ctx);
+ // ***
+ ttp.push( TextToPrint{text:"@p".to_string(),color:Rgb(HCP_StandardPurple)} );
+ ttp.push( TextToPrint{text:position_to_text(action_position),color:Rgb(HCP_Black)} );
+ // ***
+ let text_lines : Vec<Vec<TextToPrint>> = vec![ttp];
+ // ***
+ draw_firing(path_str,text_lines,gen_ctx,exe_ctx);
+}*/
+
+pub fn draw_firing_on_model_action(path_str : &String,
+ action_position : &Position,
+ action : &ObservableAction,
+ gen_ctx : &GeneralContext,
+ exe_ctx:&ExecutionContext) {
+ let mut ttp = diagram_repr_atomic_model_action(action,gen_ctx,exe_ctx);
+ // ***
+ ttp.push( TextToPrint{text:"@p".to_string(),color:Rgb(HCP_StandardPurple)} );
+ ttp.push( TextToPrint{text:position_to_text(action_position),color:Rgb(HCP_Black)} );
+ // ***
+ let text_lines : Vec<Vec<TextToPrint>> = vec![ttp];
+ // ***
+ draw_firing(path_str,text_lines,gen_ctx,exe_ctx);
+}
+
+pub fn draw_firing_on_trace_against_model_action(path_str : &String,
+ action_position : &Position,
+ trace_action : &TraceAction,
+ model_action : &ObservableAction,
+ gen_ctx : &GeneralContext,
+ exe_ctx:&ExecutionContext) {
+ let mut text_lines : Vec<Vec<TextToPrint>> = Vec::new();
+ // ***
+ {
+ let mut ttp : Vec<TextToPrint> = Vec::new();
+ ttp.append(&mut diagram_repr_atomic_model_action(model_action,gen_ctx,exe_ctx) );
+ ttp.push( TextToPrint{text:"@p".to_string(),color:Rgb(HCP_StandardPurple)} );
+ ttp.push( TextToPrint{text:position_to_text(action_position),color:Rgb(HCP_Black)} );
+ text_lines.push(ttp);
+ }
+ // ***
+ {
+ let mut ttp : Vec<TextToPrint> = vec![TextToPrint{text:"↔".to_string(),color:Rgb(HCP_StandardPurple)}];
+ ttp.append(&mut diagram_repr_atomic_trace_action(trace_action,gen_ctx,exe_ctx) );
+ text_lines.push( ttp );
+ }
+ // ***
+ draw_firing(path_str,text_lines,gen_ctx,exe_ctx);
+}
+
+fn draw_firing(path_str : &String,
+ text_lines : Vec<Vec<TextToPrint>>,
+ gen_ctx : &GeneralContext,
+ exe_ctx:&ExecutionContext) {
+ let path = Path::new( path_str );
+ // ***
+ let line_lens : Vec<usize> = text_lines.iter().map(|x| TextToPrint::char_count(x) ).collect();
+ let max_x_shift = *line_lens.iter().max().unwrap();
+ // ***
+ let img_width : f32 = 2.0*MARGIN + (max_x_shift as f32)*FONT_WIDTH/2.0;
+ let img_height : f32 = 2.0*MARGIN + (((text_lines.len()*2)-1) as f32)*VERTICAL_SIZE;
+
+ // Draw Frame
+ let mut image = RgbImage::new( img_width as u32, img_height as u32);
+ draw_filled_rect_mut(&mut image, Rect::at(0,0).of_size(img_width as u32,img_height as u32), Rgb(HCP_White));
+ // Draw Fragments
+ let mut yshift : u32 = 0;
+ for text in text_lines {
+ let msg_x_pos = (img_width/2.0) - ( (TextToPrint::char_count(&text) as f32)*FONT_WIDTH/4.0 );
+ let msg_y_pos = MARGIN + (yshift as f32)*VERTICAL_SIZE;
+ draw_colored_text(&mut image,&text,msg_x_pos,msg_y_pos);
+ yshift = yshift +2;
+ }
+ // ***
+ image.save(path).unwrap();
+}
+
+
+
diff --git a/src/rendering/custom_draw/firing/mod.rs b/src/rendering/custom_draw/firing/mod.rs
new file mode 100644
index 0000000..f1e92e1
--- /dev/null
+++ b/src/rendering/custom_draw/firing/mod.rs
@@ -0,0 +1,15 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod draw_firing;
\ No newline at end of file
diff --git a/src/rendering/custom_draw/mod.rs b/src/rendering/custom_draw/mod.rs
new file mode 100644
index 0000000..925eb89
--- /dev/null
+++ b/src/rendering/custom_draw/mod.rs
@@ -0,0 +1,18 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+mod utils;
+mod extraction;
+pub mod seqdiag;
+pub mod firing;
\ No newline at end of file
diff --git a/src/rendering/custom_draw/seqdiag/action.rs b/src/rendering/custom_draw/seqdiag/action.rs
new file mode 100644
index 0000000..51f079e
--- /dev/null
+++ b/src/rendering/custom_draw/seqdiag/action.rs
@@ -0,0 +1,369 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::cmp;
+use std::env;
+use std::collections::{HashMap,HashSet};
+
+// **********
+
+use image::{Rgb, RgbImage};
+use imageproc::rect::Rect;
+use imageproc::drawing::{
+ Point,
+ draw_cross_mut,
+ draw_line_segment_mut,
+ draw_hollow_rect_mut,
+ draw_filled_rect_mut,
+ draw_hollow_circle_mut,
+ draw_filled_circle_mut,
+ draw_convex_polygon_mut,
+ draw_text_mut
+};
+use rusttype::{FontCollection, Scale};
+
+// **********
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::interaction::{Interaction};
+use crate::core::syntax::action::*;
+
+
+use crate::rendering::sd_drawing_conf::*;
+use crate::rendering::hibou_color_palette::*;
+
+use crate::rendering::custom_draw::seqdiag::dimensions_tools::*;
+use crate::rendering::textual::colored::colored_text::*;
+
+use crate::rendering::custom_draw::utils::colored_text::draw_colored_text;
+use crate::rendering::custom_draw::utils::arrow_heads::*;
+use crate::rendering::custom_draw::seqdiag::lf_coords::DrawingLifelineCoords;
+
+// **********
+
+struct LfActToDraw{
+ lf_id : usize,
+ preamble_len : usize,
+ postamble_len : usize,
+ texts_to_print : Vec<Vec<TextToPrint>>,
+ max_txt_width : f32
+}
+
+impl LfActToDraw {
+ pub fn new(lf_id : usize,
+ preamble_len : usize,
+ postamble_len : usize,
+ texts_to_print : Vec<Vec<TextToPrint>>,
+ max_txt_width : f32) -> LfActToDraw {
+ return LfActToDraw{
+ lf_id,
+ preamble_len,
+ postamble_len,
+ texts_to_print,
+ max_txt_width
+ }
+ }
+}
+
+pub fn draw_action( image : &mut RgbImage,
+ exe_ctx: &ExecutionContext,
+ action : &ObservableAction,
+ lf_x_widths : &HashMap<usize,DrawingLifelineCoords>,
+ texts_to_print : &mut Vec<Vec<TextToPrint>>,
+ yshift : u32) -> (u32,[usize;2]) {
+
+ let mut max_preamble_len : usize = action.lf_act.preamble.len();
+ let mut max_postamble_len : usize = action.lf_act.postamble.len();
+ // ***
+ let mut min_lf_id : usize = action.lf_act.lf_id;
+ let mut max_lf_id : usize = action.lf_act.lf_id;
+ // ***
+ let msg_to_print = texts_to_print.remove(0);
+ let mut lf_actions : Vec<LfActToDraw> = Vec::new();
+ let mut arr_kinds : Vec<ActionArrowKind> = Vec::new();
+ {
+ let mut lf_act_texts : Vec<Vec<TextToPrint>> = Vec::new();
+ let mut max_txt_width : f32 = (TextToPrint::char_count(&msg_to_print) as f32)*FONT_WIDTH/2.0;
+ for txt_idx in 0..(action.lf_act.preamble.len() + action.lf_act.postamble.len()) {
+ let got_txt = texts_to_print.remove(0);
+ max_txt_width = max_txt_width.max( (TextToPrint::char_count(&got_txt) as f32)*FONT_WIDTH/2.0 );
+ lf_act_texts.push( got_txt );
+ }
+ lf_actions.push( LfActToDraw::new(action.lf_act.lf_id,
+ action.lf_act.preamble.len(),
+ action.lf_act.postamble.len(),
+ lf_act_texts,
+ max_txt_width) );
+ }
+ // ***
+ let msg_to_print_width : f32 = (TextToPrint::char_count(&msg_to_print) as f32)*FONT_WIDTH/2.0;
+ let position_to_draw_message_text : f32;
+ // ***
+ match action.act_kind {
+ ObservableActionKind::Emission(ref targets) => {
+ for target_lf_act in targets {
+ // ***
+ let mut lf_act_texts : Vec<Vec<TextToPrint>> = Vec::new();
+ let mut max_txt_width : f32 = 0.0;
+ for txt_idx in 0..(target_lf_act.preamble.len() + target_lf_act.postamble.len()) {
+ let got_txt = texts_to_print.remove(0);
+ max_txt_width = max_txt_width.max( (TextToPrint::char_count(&got_txt) as f32)*FONT_WIDTH/2.0 );
+ lf_act_texts.push( got_txt );
+ }
+ // ***
+ max_preamble_len = cmp::max(max_preamble_len,target_lf_act.preamble.len());
+ max_postamble_len = cmp::max(max_postamble_len,target_lf_act.postamble.len());
+ // ***
+ min_lf_id = cmp::min(min_lf_id, target_lf_act.lf_id);
+ max_lf_id = cmp::max(max_lf_id, target_lf_act.lf_id);
+ // ***
+ lf_actions.push( LfActToDraw::new(target_lf_act.lf_id,target_lf_act.preamble.len(),target_lf_act.postamble.len(),lf_act_texts,max_txt_width) );
+ }
+ if lf_actions.len() == 1 {
+ {
+ let main_lf_coords = lf_x_widths.get(&action.lf_act.lf_id).unwrap();
+ position_to_draw_message_text = main_lf_coords.x_middle + (main_lf_coords.x_span_inner/4.0);
+ }
+ arr_kinds.push( ActionArrowKind::Emission );
+ draw_action_content(image,exe_ctx,max_preamble_len,lf_actions,arr_kinds,lf_x_widths,yshift,None);
+ } else if lf_actions.len() == 2 {
+ {
+ let origin_lf_id = *(&action.lf_act.lf_id);
+ let origin_lf_coords = lf_x_widths.get(&origin_lf_id).unwrap();
+ let target_lf_id = (&lf_actions).get(1).unwrap().lf_id;
+ let mut anchor_lf_id : usize = target_lf_id;
+ if target_lf_id == origin_lf_id {
+ panic!("cannot draw emission then reception on the same lifeline");
+ } else if target_lf_id < origin_lf_id {
+ let mut lf_id_shift : usize = 1;
+ while !lf_x_widths.contains_key(&(origin_lf_id - lf_id_shift)) {
+ lf_id_shift = lf_id_shift + 1 ;
+ }
+ anchor_lf_id = (origin_lf_id - lf_id_shift);
+ } else if target_lf_id > origin_lf_id {
+ let mut lf_id_shift : usize = 1;
+ while !lf_x_widths.contains_key(&(origin_lf_id + lf_id_shift)) {
+ lf_id_shift = lf_id_shift + 1 ;
+ }
+ anchor_lf_id = (origin_lf_id + lf_id_shift);
+ }
+ let anchor_lf_coords = lf_x_widths.get(&anchor_lf_id).unwrap();
+ position_to_draw_message_text = (origin_lf_coords.x_middle + anchor_lf_coords.x_middle)/2.0;
+ }
+ arr_kinds.push( ActionArrowKind::None );
+ arr_kinds.push( ActionArrowKind::None );
+ let tar_lf_id = lf_actions.get(1).unwrap().lf_id;
+ draw_action_content(image,exe_ctx,max_preamble_len,lf_actions,arr_kinds,lf_x_widths,yshift,Some((action.lf_act.lf_id,tar_lf_id)));
+ } else {
+ {
+ let main_lf_coords = lf_x_widths.get(&action.lf_act.lf_id).unwrap();
+ position_to_draw_message_text = main_lf_coords.x_middle + (main_lf_coords.x_span_inner/2.0);
+ }
+ arr_kinds.push( ActionArrowKind::BroadcastEmission );
+ for idx in 1..lf_actions.len() {
+ arr_kinds.push( ActionArrowKind::BroadcastReception );
+ }
+ draw_action_content(image,exe_ctx,max_preamble_len,lf_actions,arr_kinds,lf_x_widths,yshift,None);
+ }
+ },
+ ObservableActionKind::Reception => {
+ {
+ let main_lf_coords = lf_x_widths.get(&action.lf_act.lf_id).unwrap();
+ position_to_draw_message_text = main_lf_coords.x_middle - (main_lf_coords.x_span_inner/4.0);
+ }
+ arr_kinds.push( ActionArrowKind::Reception );
+ draw_action_content(image,exe_ctx,max_preamble_len,lf_actions,arr_kinds,lf_x_widths,yshift,None);
+ }
+ }
+ // ***
+ let text_y_pos = get_y_pos_from_yshift(yshift + 2*(max_preamble_len as u32));
+ draw_colored_text(image,&msg_to_print,position_to_draw_message_text - msg_to_print_width/2.0,text_y_pos);
+ // ***
+ let new_yshift = yshift + 2 + 2*((max_preamble_len + max_postamble_len) as u32);
+ return (new_yshift,[min_lf_id,max_lf_id]);
+}
+
+
+
+
+// **********
+
+#[derive(Clone, PartialEq, Debug, Copy)]
+enum ActionArrowKind {
+ Emission,
+ Reception,
+ BroadcastEmission,
+ BroadcastReception,
+ None
+}
+
+
+fn draw_colored_text_centered_in_box(image: &mut RgbImage,
+ xpos : f32,
+ width : f32,
+ ypos : f32,
+ to_print : &Vec<TextToPrint>) {
+ let width_with_margin = width + 2.0*MARGIN;
+ let zone_rect = Rect::at((xpos-width_with_margin/2.0) as i32, (ypos - VERTICAL_SIZE) as i32).of_size(width_with_margin as u32, 2*VERTICAL_SIZE as u32);
+ draw_filled_rect_mut(image,zone_rect,Rgb(HCP_BrightGray));
+ let text_width = (TextToPrint::char_count(&to_print) as f32)*FONT_WIDTH/2.0;
+ draw_colored_text(image,to_print,xpos-(text_width/2.0),ypos);
+}
+
+fn draw_centered_colored_text(image: &mut RgbImage,
+ xpos : f32,
+ width : f32,
+ ypos : f32,
+ to_print : &Vec<TextToPrint>) {
+ let text_width = (TextToPrint::char_count(&to_print) as f32)*FONT_WIDTH/2.0;
+ draw_colored_text(image,to_print,xpos-(text_width/2.0),ypos);
+}
+
+fn draw_message_arrow(image : &mut RgbImage,
+ arr_kind : &ActionArrowKind,
+ lf_x_coords : &DrawingLifelineCoords,
+ arrow_y_shift : u32) {
+ let event_y_pos : f32 = get_y_pos_from_yshift(arrow_y_shift);
+ match arr_kind {
+ &ActionArrowKind::Emission => {
+ let msg_x_left = lf_x_coords.x_middle;
+ let msg_x_right= msg_x_left + lf_x_coords.x_span_inner/2.0;
+ draw_arrowhead_rightward(image,msg_x_right,event_y_pos,Rgb(HCP_Black));
+ draw_line_segment_mut(image,
+ (msg_x_left, event_y_pos),
+ (msg_x_right, event_y_pos),
+ Rgb(HCP_Black));
+ },
+ &ActionArrowKind::Reception => {
+ let msg_x_right = lf_x_coords.x_middle;
+ let msg_x_left= msg_x_right - lf_x_coords.x_span_inner/2.0;
+ draw_filled_circle_mut(image, (msg_x_left as i32, event_y_pos as i32), 3, Rgb(HCP_Black));
+ draw_arrowhead_rightward(image,msg_x_right,event_y_pos,Rgb(HCP_Black));
+ draw_line_segment_mut(image,
+ (msg_x_left, event_y_pos),
+ (msg_x_right, event_y_pos),
+ Rgb(HCP_Black));
+ },
+ ActionArrowKind::BroadcastEmission => {
+ let msg_x_left = lf_x_coords.x_middle;
+ let msg_x_right= msg_x_left + lf_x_coords.x_span_inner/2.0;
+ draw_double_half_ellipsis_rightward(image,msg_x_right, event_y_pos,Rgb(HCP_Black));
+ draw_line_segment_mut(image,
+ (msg_x_left, event_y_pos),
+ (msg_x_right, event_y_pos),
+ Rgb(HCP_Black));
+ },
+ ActionArrowKind::BroadcastReception => {
+ let msg_x_right = lf_x_coords.x_middle;
+ let msg_x_left= msg_x_right - lf_x_coords.x_span_inner/2.0;
+ draw_double_half_ellipsis_rightward(image, msg_x_left, event_y_pos,Rgb(HCP_Black));
+ draw_line_segment_mut(image,
+ (msg_x_left, event_y_pos),
+ (msg_x_right, event_y_pos),
+ Rgb(HCP_Black));
+ },
+ ActionArrowKind::None => {}
+ }
+}
+
+fn draw_lf_act(image : &mut RgbImage,
+ atd : &LfActToDraw,
+ arr_kind : &ActionArrowKind,
+ lf_x_widths : &HashMap<usize,DrawingLifelineCoords>,
+ yshift: u32,
+ max_preamble_len : usize) {
+ let lf_x_coords = lf_x_widths.get(&atd.lf_id).unwrap();
+ // ***
+ let mut lf_yshift : u32 = yshift + 2*(max_preamble_len as u32) - 2*(atd.preamble_len as u32);
+ // ***
+ if atd.preamble_len + atd.postamble_len > 0 {
+ let zone_width : f32 = atd.max_txt_width + 2.0*MARGIN;
+ let zone_left : i32 = (lf_x_coords.x_middle-zone_width/2.0) as i32;
+ // ***
+ let zone_top : i32 = get_y_pos_from_yshift(lf_yshift - 1) as i32;
+ let height_yshift : usize = (atd.preamble_len + atd.postamble_len)*2 + 4;
+ // ***
+ let zone_height : f32 = (height_yshift as f32)*VERTICAL_SIZE;
+ // ***
+ let zone_rect = Rect::at( zone_left, zone_top).of_size(zone_width as u32, zone_height as u32);
+ draw_filled_rect_mut(image,zone_rect,Rgb(HCP_BrightGray));
+ }
+ // ***
+ let mut current_txt_id : usize = 0;
+ // ***
+ for id in 0..atd.preamble_len {
+ let to_print = atd.texts_to_print.get(current_txt_id).unwrap();
+ current_txt_id = current_txt_id +1;
+ draw_centered_colored_text(image, lf_x_coords.x_middle,atd.max_txt_width,get_y_pos_from_yshift(lf_yshift),to_print);
+ lf_yshift = lf_yshift +2;
+ }
+ // ***
+ lf_yshift = lf_yshift +2;
+ let arrow_y_shift = lf_yshift;
+ lf_yshift = lf_yshift +1;
+ // ***
+ for id in 0..atd.postamble_len {
+ let to_print = atd.texts_to_print.get(current_txt_id).unwrap();
+ current_txt_id = current_txt_id +1;
+ draw_centered_colored_text(image, lf_x_coords.x_middle,atd.max_txt_width,get_y_pos_from_yshift(lf_yshift),to_print);
+ lf_yshift = lf_yshift +2;
+ }
+ // ***
+ // we do it afterwards so that the gray squares are not painted over the arrows but stay under
+ draw_message_arrow(image,arr_kind,lf_x_coords,arrow_y_shift);
+}
+
+
+fn draw_action_content( image : &mut RgbImage,
+ exe_ctx : &ExecutionContext,
+ max_preamble_len : usize,
+ lf_actions : Vec<LfActToDraw>,
+ arr_kinds : Vec<ActionArrowKind>,
+ lf_x_widths : &HashMap<usize,DrawingLifelineCoords>,
+ yshift: u32,
+ draw_passing : Option<(usize,usize)>) {
+ // ***
+ for idx in 0..lf_actions.len() {
+ let atd : &LfActToDraw = lf_actions.get(idx).unwrap();
+ let arr_kind : &ActionArrowKind = arr_kinds.get(idx).unwrap();
+ draw_lf_act(image,atd,arr_kind,lf_x_widths,
+ yshift,max_preamble_len);
+ }
+ // ***
+ match draw_passing {
+ None => {},
+ Some( (origin_lf_id, target_lf_id) ) => {
+ let arrow_y_pos = get_y_pos_from_yshift(yshift + 2 + 2*(max_preamble_len as u32));
+ let msg_x_orig : f32 = lf_x_widths.get(&origin_lf_id).unwrap().x_middle;
+ let msg_x_targ : f32 = lf_x_widths.get(&target_lf_id).unwrap().x_middle;
+ if origin_lf_id < target_lf_id {
+ draw_arrowhead_rightward(image,msg_x_targ,arrow_y_pos,Rgb(HCP_Black));
+ } else {
+ draw_arrowhead_leftward(image,msg_x_targ,arrow_y_pos,Rgb(HCP_Black));
+ }
+ draw_line_segment_mut(image,
+ (msg_x_targ, arrow_y_pos),
+ (msg_x_orig, arrow_y_pos),
+ Rgb(HCP_Black));
+ }
+ }
+}
+
+
+
+
+
+
+
diff --git a/src/rendering/custom_draw/seqdiag/dimensions_tools.rs b/src/rendering/custom_draw/seqdiag/dimensions_tools.rs
new file mode 100644
index 0000000..456bcea
--- /dev/null
+++ b/src/rendering/custom_draw/seqdiag/dimensions_tools.rs
@@ -0,0 +1,95 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+use std::cmp;
+
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::action::*;
+use crate::core::syntax::interaction::{Interaction};
+
+use crate::rendering::sd_drawing_conf::*;
+use crate::rendering::custom_draw::seqdiag::recursive_frag::*;
+
+
+pub fn get_interaction_max_yshift(interaction : &Interaction, exe_ctx : &ExecutionContext) -> usize {
+ let mut cpt = 4;
+ cpt += get_interaction_depth(interaction, exe_ctx);
+ return cpt;
+}
+
+fn get_interaction_depth(interaction : &Interaction, exe_ctx : &ExecutionContext) -> usize {
+ match interaction {
+ &Interaction::Empty => {return 0},
+ &Interaction::Action(ref act) => {
+ match &act.act_kind {
+ ObservableActionKind::Reception => {
+ return 4 + 2*(act.lf_act.preamble.len() + act.lf_act.postamble.len());
+ },
+ ObservableActionKind::Emission(targets) => {
+ let mut max_preamble_len : usize = act.lf_act.preamble.len();
+ let mut max_postamble_len : usize = act.lf_act.postamble.len();
+ // ***
+ for target in targets {
+ max_preamble_len = cmp::max(max_preamble_len, target.preamble.len());
+ max_postamble_len = cmp::max(max_postamble_len, target.postamble.len());
+ }
+ // ***
+ return 4 + 2*(max_preamble_len + max_postamble_len);
+ }
+ }
+ },
+ &Interaction::Strict(ref i1, ref i2) => {
+ let mut frags = get_recursive_strict_frags(i1);
+ frags.extend( get_recursive_strict_frags(i2) );
+ let mut sum : usize = 2;
+ for frag in frags {
+ sum = sum + get_interaction_depth(frag,exe_ctx) + 2;
+ }
+ return sum;
+ },
+ &Interaction::Seq(ref i1, ref i2) => {
+ return get_interaction_depth(i1,exe_ctx) + get_interaction_depth(i2,exe_ctx) + 1;
+ },
+ &Interaction::Alt(ref i1, ref i2) => {
+ let mut frags = get_recursive_alt_frags(i1);
+ frags.extend( get_recursive_alt_frags(i2) );
+ let mut sum : usize = 2;
+ for frag in frags {
+ sum = sum + get_interaction_depth(frag,exe_ctx) + 2;
+ }
+ return sum;
+ },
+ &Interaction::Par(ref i1, ref i2) => {
+ let mut frags = get_recursive_par_frags(i1);
+ frags.extend( get_recursive_par_frags(i2) );
+ let mut sum : usize = 2;
+ for frag in frags {
+ sum = sum + get_interaction_depth(frag,exe_ctx) + 2;
+ }
+ return sum;
+ },
+ &Interaction::Scope(_, ref i1) => {
+ return get_interaction_depth(i1,exe_ctx) + 4;
+ }
+ &Interaction::Loop(_, ref i1) => {
+ return get_interaction_depth(i1,exe_ctx) + 4;
+ }
+ }
+}
+
+pub fn get_y_pos_from_yshift(yshift : u32) -> f32 {
+ return MARGIN + VERTICAL_SIZE*(yshift as f32);
+}
+
diff --git a/src/rendering/custom_draw/seqdiag/img_content.rs b/src/rendering/custom_draw/seqdiag/img_content.rs
new file mode 100644
index 0000000..57044b5
--- /dev/null
+++ b/src/rendering/custom_draw/seqdiag/img_content.rs
@@ -0,0 +1,232 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::env;
+use std::collections::{HashMap,HashSet};
+use std::cmp;
+
+// **********
+
+use image::{Rgb, RgbImage};
+use imageproc::drawing::{
+ Point,
+ draw_cross_mut,
+ draw_line_segment_mut,
+ draw_hollow_rect_mut,
+ draw_filled_rect_mut,
+ draw_hollow_circle_mut,
+ draw_filled_circle_mut,
+ draw_convex_polygon_mut,
+ draw_text_mut
+};
+use rusttype::{FontCollection, Scale};
+
+// **********
+
+use crate::core::syntax::interaction::{Interaction,ScheduleOperatorKind};
+use crate::core::syntax::action::*;
+use crate::core::context::general::GeneralContext;
+
+use crate::core::context::execution::ExecutionContext;
+
+use crate::rendering::sd_drawing_conf::*;
+use crate::rendering::textual::convention::*;
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::custom_draw::seqdiag::recursive_frag::*;
+use crate::rendering::custom_draw::seqdiag::dimensions_tools::*;
+use crate::rendering::custom_draw::seqdiag::action::draw_action;
+use crate::rendering::custom_draw::seqdiag::lf_coords::DrawingLifelineCoords;
+use crate::rendering::hibou_color_palette::*;
+use crate::rendering::custom_draw::utils::colored_text::draw_colored_text;
+// **********
+
+
+
+// **********
+
+pub fn draw_interaction_rec( image : &mut RgbImage,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ interaction : &Interaction,
+ lf_x_widths : &HashMap<usize,DrawingLifelineCoords>,
+ texts_to_print : &mut Vec<Vec<TextToPrint>>,
+ nest_shift : &mut u32,
+ yshift : &mut u32)
+ -> [usize;2] { // returns left and right borders of the interaction
+ match interaction {
+ &Interaction::Empty => {
+ return [gen_ctx.get_lf_num(),0]; // because when going up we keep the minimum on the left and maximum on the right
+ },
+ &Interaction::Action(ref act) => {
+ *yshift = *yshift +1;
+ let (new_yshift,lr_bounds) = draw_action(image,exe_ctx,act,lf_x_widths,texts_to_print,*yshift);
+ *yshift = new_yshift + 1;
+ return lr_bounds;
+ },
+ &Interaction::Seq(ref i1,ref i2) => {
+ let wr1 : [usize;2] = draw_interaction_rec(image, gen_ctx, exe_ctx,i1, lf_x_widths, texts_to_print, nest_shift, yshift);
+ *yshift = *yshift +1;
+ let wr2 : [usize;2] = draw_interaction_rec(image, gen_ctx, exe_ctx,i2, lf_x_widths, texts_to_print, nest_shift, yshift);
+ return [ std::cmp::min(wr1[0],wr2[0]) , std::cmp::max(wr1[1],wr2[1]) ];
+ },
+ &Interaction::Strict(ref i1,ref i2) => {
+ let mut frags = get_recursive_strict_frags(i1);
+ frags.extend( get_recursive_strict_frags(i2) );
+ let label = vec![TextToPrint{text:SYNTAX_STRICT.to_string(),color:Rgb(HCP_Black)}];
+ return draw_n_ary_combined_fragment(image, gen_ctx, exe_ctx,frags,lf_x_widths,texts_to_print, label, nest_shift, yshift);
+ },
+ &Interaction::Alt(ref i1,ref i2) => {
+ let mut frags = get_recursive_alt_frags(i1);
+ frags.extend( get_recursive_alt_frags(i2) );
+ let label = vec![TextToPrint{text:SYNTAX_ALT.to_string(),color:Rgb(HCP_Black)}];
+ return draw_n_ary_combined_fragment(image, gen_ctx, exe_ctx,frags,lf_x_widths,texts_to_print, label, nest_shift, yshift);
+ },
+ &Interaction::Par(ref i1,ref i2) => {
+ let mut frags = get_recursive_par_frags(i1);
+ frags.extend( get_recursive_par_frags(i2) );
+ let label = vec![TextToPrint{text:SYNTAX_PAR.to_string(),color:Rgb(HCP_Black)}];
+ return draw_n_ary_combined_fragment(image, gen_ctx, exe_ctx,frags,lf_x_widths,texts_to_print, label, nest_shift, yshift);
+ },
+ &Interaction::Scope(_, ref i1) => {
+ let mut label : Vec<TextToPrint> = Vec::new();
+ label.push( TextToPrint{text:"scope{".to_string(),color:Rgb(HCP_Black)});
+ let mut scope_content = texts_to_print.remove(0);
+ label.append( &mut scope_content);
+ label.push( TextToPrint{text:"}".to_string(),color:Rgb(HCP_Black)});
+ return draw_unary_combined_fragment(image, gen_ctx, exe_ctx,i1,lf_x_widths,texts_to_print, label, nest_shift, yshift);
+ },
+ &Interaction::Loop(ref lkind, ref i1) => {
+ match lkind {
+ ScheduleOperatorKind::Strict => {
+ let label = vec![TextToPrint{text:SYNTAX_LOOP_STRICT.to_string(),color:Rgb(HCP_Black)}];
+ return draw_unary_combined_fragment(image, gen_ctx, exe_ctx,i1,lf_x_widths,texts_to_print, label, nest_shift, yshift);
+ },
+ ScheduleOperatorKind::Seq => {
+ let label = vec![TextToPrint{text:SYNTAX_LOOP_SEQ.to_string(),color:Rgb(HCP_Black)}];
+ return draw_unary_combined_fragment(image, gen_ctx, exe_ctx,i1,lf_x_widths,texts_to_print, label, nest_shift, yshift);
+ },
+ ScheduleOperatorKind::Par => {
+ let label = vec![TextToPrint{text:SYNTAX_LOOP_PAR.to_string(),color:Rgb(HCP_Black)}];
+ return draw_unary_combined_fragment(image, gen_ctx, exe_ctx,i1,lf_x_widths,texts_to_print, label, nest_shift, yshift);
+ }
+ }
+ }
+ }
+}
+
+fn draw_unary_combined_fragment( image : &mut RgbImage,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ i1 : &Interaction,
+ lf_x_widths : &HashMap<usize,DrawingLifelineCoords>,
+ texts_to_print : &mut Vec<Vec<TextToPrint>>,
+ label : Vec<TextToPrint>,
+ nest_shift : &mut u32,
+ yshift : &mut u32) -> [usize;2] {
+ // draw content and gather data
+ *nest_shift += 1;
+ let start_y : u32 = *yshift;
+ *yshift += 3;
+ let lr_bounds : [usize;2] = draw_interaction_rec(image, gen_ctx, exe_ctx,i1, lf_x_widths, texts_to_print, nest_shift, yshift);
+ *yshift += 1;
+ let end_y : u32 = *yshift;
+ *nest_shift -= 1;
+ // draw frame
+ let mut y_drafts : Vec<u32> = [start_y,end_y].to_vec();
+ draw_combined_fragment_frame(image, label, *nest_shift,lf_x_widths,lr_bounds[0],lr_bounds[1],y_drafts);
+ return lr_bounds;
+}
+
+fn draw_n_ary_combined_fragment( image : &mut RgbImage,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ sub_ints : Vec<&Interaction>,
+ lf_x_widths : &HashMap<usize,DrawingLifelineCoords>,
+ texts_to_print : &mut Vec<Vec<TextToPrint>>,
+ label : Vec<TextToPrint>,
+ nest_shift : &mut u32,
+ yshift : &mut u32) -> [usize;2] {
+ let mut y_drafts : Vec<u32> = Vec::new();
+ // draw content and gather data
+ *nest_shift += 1;
+ y_drafts.push(*yshift);
+ *yshift += 2;
+ //
+ let mut min_lf_id : usize = gen_ctx.get_lf_num();
+ let mut max_lf_id : usize = 0;
+ for my_int in sub_ints {
+ *yshift += 1;
+ let lr_bounds = draw_interaction_rec(image, gen_ctx, exe_ctx,my_int, lf_x_widths, texts_to_print, nest_shift, yshift);
+ min_lf_id = cmp::min( min_lf_id, lr_bounds[0]);
+ max_lf_id = cmp::max( max_lf_id, lr_bounds[1]);
+ *yshift += 1;
+ y_drafts.push(*yshift);
+ }
+ *nest_shift -= 1;
+ //
+ let lr_bounds: [usize;2] = [ min_lf_id, max_lf_id ];
+ // draw frame
+ draw_combined_fragment_frame(image,label,*nest_shift,lf_x_widths,lr_bounds[0],lr_bounds[1],y_drafts);
+ return lr_bounds;
+}
+
+fn draw_combined_fragment_frame( image : &mut RgbImage,
+ label : Vec<TextToPrint>,
+ nest_shift : u32,
+ lf_x_widths : &HashMap<usize,DrawingLifelineCoords>,
+ left_bound : usize,
+ right_bound : usize,
+ y_drafts : Vec<u32>) {
+ let left_lf_coords = lf_x_widths.get(&left_bound).unwrap();
+ let x_left : f32 = left_lf_coords.x_start + (nest_shift as f32)*FRAGMENT_PADDING;
+ let right_lf_coords = lf_x_widths.get(&right_bound).unwrap();
+ let x_right : f32 = (right_lf_coords.x_start + right_lf_coords.x_span_outer) - (nest_shift as f32)*FRAGMENT_PADDING;
+
+ let mut y_coords : Vec<f32> = y_drafts.into_iter().map(|y| get_y_pos_from_yshift(y) ).collect::< Vec<f32> >();
+ let y_start : f32 = y_coords[0];// + *nest_shift*FRAGMENT_PADDING;
+ y_coords.drain(0..0);
+ let y_end : f32 = y_coords.pop().unwrap();// - (nest_shift as f32)*FRAGMENT_PADDING;
+ draw_line_segment_mut(image,
+ (x_left, y_start),
+ (x_left, y_end),
+ Rgb(HCP_Black));
+ draw_line_segment_mut(image,
+ (x_right, y_start),
+ (x_right, y_end),
+ Rgb(HCP_Black));
+ draw_line_segment_mut(image,
+ (x_left, y_start),
+ (x_right, y_start),
+ Rgb(HCP_Black));
+ draw_line_segment_mut(image,
+ (x_left, y_end),
+ (x_right, y_end),
+ Rgb(HCP_Black));
+ for y_coord in y_coords {
+ draw_line_segment_mut(image,
+ (x_left, y_coord),
+ (x_right, y_coord),
+ Rgb(HCP_Black));
+ }
+ let font = FontCollection::from_bytes(HIBOU_GRAPHIC_FONT).unwrap().into_font().unwrap();
+
+ let scale = Scale { x: FONT_WIDTH, y: FONT_HEIGHT };
+ draw_colored_text(image,&label,x_left+FRAGMENT_TITLE_MARGIN,y_start + VERTICAL_SIZE);
+}
+
+
+
+
+
+
diff --git a/src/rendering/custom_draw/seqdiag/img_frame.rs b/src/rendering/custom_draw/seqdiag/img_frame.rs
new file mode 100644
index 0000000..8f2bf29
--- /dev/null
+++ b/src/rendering/custom_draw/seqdiag/img_frame.rs
@@ -0,0 +1,139 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::env;
+use std::collections::HashMap;
+use std::path::Path;
+
+// **********
+
+use image::{Rgb, RgbImage};
+use imageproc::rect::Rect;
+use imageproc::drawing::{
+ Point,
+ draw_cross_mut,
+ draw_line_segment_mut,
+ draw_hollow_rect_mut,
+ draw_filled_rect_mut,
+ draw_hollow_circle_mut,
+ draw_filled_circle_mut,
+ draw_convex_polygon_mut,
+ draw_text_mut
+};
+use rusttype::{FontCollection, Scale};
+
+// **********
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::rendering::custom_draw::seqdiag::dimensions_tools::*;
+use crate::rendering::sd_drawing_conf::*;
+use crate::rendering::hibou_color_palette::*;
+use crate::rendering::custom_draw::seqdiag::lf_coords::DrawingLifelineCoords;
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::custom_draw::utils::colored_text::draw_colored_text;
+/*
+ DRAWING FUNCTION
+*/
+
+
+
+
+pub fn draw_frame(image : &mut RgbImage, img_width : &f32, img_height : &f32, max_y_shift : usize) {
+ draw_filled_rect_mut(image, Rect::at(0,0).of_size(*img_width as u32,*img_height as u32), Rgb(HCP_White));
+ /*
+ for x in 0..max_y_shift {
+ let y_pos : f32 = MARGIN + ((x as f32)*VERTICAL_SIZE);
+ draw_line_segment_mut(image, (0.5,y_pos), (img_width - 0.5,y_pos), Rgb(HCP_DarkCyan));
+ }*/
+ /*
+ draw_hollow_rect_mut(image,
+ Rect::at((MARGIN) as i32,(MARGIN) as i32).of_size((img_width -2.0*MARGIN) as u32, (img_height -2.0*MARGIN) as u32),
+ Rgb(HC_Grammar_Symbol));
+
+ let font = FontCollection::from_bytes(HIBOU_GRAPHIC_FONT).unwrap().into_font().unwrap();
+
+ let scale = Scale { x: FONT_WIDTH, y: FONT_HEIGHT };
+ draw_text_mut(image,
+ Rgb(HC_Grammar_Symbol),
+ (MARGIN+THICKNESS+FRAGMENT_TITLE_MARGIN) as u32,
+ (MARGIN+THICKNESS) as u32,
+ scale,
+ &font,
+ &label
+ );*/
+}
+
+pub fn draw_lifelines(image : &mut RgbImage,
+ lf_x_widths : &HashMap<usize,DrawingLifelineCoords>,
+ inner_height : f32,
+ gen_ctx:&GeneralContext,
+ exe_ctx:&ExecutionContext,
+ init_lf_interpretations : HashMap< usize,(usize,Vec<Vec<TextToPrint>>) >) {
+ // Draw Lifelines
+ let lifeline_y_start :f32 = MARGIN + (2 as f32)*VERTICAL_SIZE;;
+ let lifeline_y_end :f32 = MARGIN+inner_height;
+ for (lf_id,lf_coords) in lf_x_widths.iter() {
+ // ***
+ let lf_name = exe_ctx.get_lf_name(gen_ctx,*lf_id).unwrap();
+ let lf_name_span = FONT_WIDTH*(lf_name.chars().count() as f32)/2.0;
+ let mut square_span_with_margin = lf_name_span + 2.0*MARGIN;
+
+ let font = FontCollection::from_bytes(HIBOU_GRAPHIC_FONT).unwrap().into_font().unwrap();
+
+ let scale = Scale { x: FONT_WIDTH, y: FONT_HEIGHT };
+
+ let label = vec![TextToPrint{text:lf_name,color:Rgb(HC_Lifeline)}];
+ let lf_label_centered_pos = lf_coords.x_middle - lf_name_span/2.0;
+ draw_colored_text(image,&label,lf_label_centered_pos,lifeline_y_start + VERTICAL_SIZE/2.0);
+ // ***
+ // Draw current interpretation
+ let mut yshift : usize = 2;
+ // draw interpretation
+ match init_lf_interpretations.get(lf_id) {
+ None => {},
+ Some( (_,assignments_to_print) ) => {
+ for ttp in assignments_to_print {
+ let ttp_size = (TextToPrint::char_count(ttp) as f32)*FONT_WIDTH/2.0;
+ let ttp_size_with_margins = ttp_size + 2.0*MARGIN;
+ square_span_with_margin = square_span_with_margin.max(ttp_size_with_margins);
+ let ttp_text_start = lf_coords.x_middle - ttp_size/2.0;
+ let ttp_rect_start = lf_coords.x_middle - ttp_size_with_margins/2.0;
+ let ttp_y_text = lifeline_y_start + (yshift as f32)*VERTICAL_SIZE + VERTICAL_SIZE/2.0;
+ let ttp_y_rect = ttp_y_text -0.5*VERTICAL_SIZE;
+ draw_filled_rect_mut(image, Rect::at(ttp_rect_start as i32,ttp_y_rect as i32).of_size(ttp_size_with_margins as u32,(VERTICAL_SIZE*2.0) as u32), Rgb(HCP_BrightGray));
+ draw_colored_text(image,ttp,ttp_text_start,ttp_y_text);
+ yshift = yshift +2;
+ }
+ }
+ }
+ // ***
+ let actor_x_start : f32 = lf_coords.x_middle - (square_span_with_margin/2.0);
+ draw_hollow_rect_mut(image,
+ Rect::at(actor_x_start as i32, lifeline_y_start as i32).of_size(square_span_with_margin as u32, ((yshift as f32)*VERTICAL_SIZE) as u32),
+ Rgb(HC_Grammar_Symbol));
+ // ***
+ draw_line_segment_mut(image,
+ (lf_coords.x_middle, lifeline_y_start + (yshift as f32)*VERTICAL_SIZE),
+ (lf_coords.x_middle, lifeline_y_end),
+ Rgb(HC_Grammar_Symbol));
+ }
+}
+
+
+
+
+
+
+
diff --git a/src/rendering/custom_draw/seqdiag/interaction.rs b/src/rendering/custom_draw/seqdiag/interaction.rs
new file mode 100644
index 0000000..4aee042
--- /dev/null
+++ b/src/rendering/custom_draw/seqdiag/interaction.rs
@@ -0,0 +1,161 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashSet;
+use std::cmp;
+use std::path::Path;
+use std::collections::HashMap;
+
+// **********
+
+use image::Rgb;
+use image::RgbImage;
+
+// **********
+
+use crate::core::syntax::interaction::*;
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::trace::*;
+
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::sd_drawing_conf::*;
+use crate::rendering::custom_draw::seqdiag::dimensions_tools::*;
+use crate::rendering::custom_draw::seqdiag::img_frame::*;
+use crate::rendering::custom_draw::seqdiag::img_content::*;
+use crate::rendering::custom_draw::extraction::ext_interaction::extract_texts_on_interaction;
+use crate::rendering::custom_draw::extraction::ext_context::extract_texts_on_interpretation;
+use crate::rendering::custom_draw::extraction::ext_multi_trace::extract_texts_on_multi_trace;
+use crate::rendering::custom_draw::seqdiag::lf_coords::DrawingLifelineCoords;
+use crate::rendering::hibou_color_palette::*;
+use crate::rendering::custom_draw::utils::colored_text::draw_colored_text;
+// **********
+
+
+
+pub fn draw_interaction(path_str : &String,
+ interaction : &Interaction,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ remaining_multi_trace : &Option<AnalysableMultiTrace>) {
+ let path = Path::new( path_str );
+ // ***
+ let (mut lf_char_widths,mut texts_to_print) = extract_texts_on_interaction(interaction,gen_ctx,exe_ctx);
+ // ***
+ let mut additional_y_space_for_context : usize = 0;
+ let init_lf_interpretations = extract_texts_on_interpretation(gen_ctx,exe_ctx);
+ let lf_keys : Vec<usize> = lf_char_widths.keys().cloned().collect();
+ for lf_id in lf_keys {
+ let mut lf_additional_y_space : usize = 0;
+ match init_lf_interpretations.get(&lf_id) {
+ None => {},
+ Some( (width_from_context,lf_init_texts) ) => {
+ lf_additional_y_space = lf_additional_y_space + lf_init_texts.len();
+ // ***
+ let lf_cwidth = lf_char_widths.get(&lf_id).unwrap();
+ lf_char_widths.insert( lf_id, cmp::max(*lf_cwidth,*width_from_context) );
+ }
+ }
+ additional_y_space_for_context = cmp::max(additional_y_space_for_context,lf_additional_y_space);
+ }
+ // ***
+ let mut lf_x_widths : HashMap<usize,DrawingLifelineCoords> = HashMap::new();
+ let mut current_x : f32 = MARGIN;
+ for lf_id in 0..gen_ctx.get_lf_num() {
+ match lf_char_widths.get(&lf_id) {
+ None => {},
+ Some(lf_char_width) => {
+ let mut max_lf_char_width : usize = *lf_char_width;
+ let span_inner = (HORIZONTAL_SIZE - 2.0*MARGIN).max( 2.0*MARGIN + (*lf_char_width as f32)*FONT_WIDTH/2.0 );
+ let span_outer = span_inner + 2.0*MARGIN;
+ let middle = current_x + (span_outer/2.0) + THICKNESS;
+ lf_x_widths.insert(lf_id,DrawingLifelineCoords{x_start:current_x,
+ x_span_inner:span_inner,
+ x_span_outer:span_outer,
+ x_middle:middle});
+ current_x = current_x + span_outer + MARGIN;
+ }
+ }
+ }
+ //current_x = current_x + MARGIN;
+ // ***
+ let max_y_shift = 2 + get_interaction_max_yshift(interaction,exe_ctx) + additional_y_space_for_context*2;
+ let mut inner_height : f32 = (max_y_shift as f32)*VERTICAL_SIZE;
+
+ // ***
+ let mut img_width : f32 = current_x;
+ let multi_trace_txttoprint : Option<(Vec<Vec<TextToPrint>>,f32)>;
+ match remaining_multi_trace {
+ None => {
+ multi_trace_txttoprint = None;
+ }
+ Some( multi_trace ) => {
+ let mt_ttp = extract_texts_on_multi_trace( gen_ctx, exe_ctx, multi_trace);
+ let mut max_char_count = 0;
+ for ttp in &mt_ttp {
+ max_char_count = max_char_count.max(TextToPrint::char_count(ttp) );
+ }
+ let mt_print_width = (max_char_count as f32)*FONT_WIDTH/2.0;
+ img_width = current_x + mt_print_width;
+ // ***
+ inner_height = inner_height.max( ((2*mt_ttp.len()) as f32)*VERTICAL_SIZE );
+ // ***
+ multi_trace_txttoprint = Some( (mt_ttp,mt_print_width) );
+ }
+ }
+ // ***
+ let mut path_condition_ttp : Vec<TextToPrint>;
+ {
+ path_condition_ttp = vec![TextToPrint{text:"π=".to_string(),color:Rgb(HCP_Black)}];
+ path_condition_ttp.append(&mut (exe_ctx.get_path_condition()).to_colored_text(gen_ctx,exe_ctx) );
+ let mt_print_width = (TextToPrint::char_count(&path_condition_ttp) as f32)*FONT_WIDTH/2.0;
+ img_width = img_width.max(2.0*MARGIN + mt_print_width);
+ }
+ // ***
+ let img_height : f32 = inner_height + 2.0*MARGIN;
+
+ // Draw Frame
+ let mut image = RgbImage::new( img_width as u32, img_height as u32);
+ draw_frame(&mut image, &img_width, &img_height, max_y_shift);
+
+ // Draw Path Condition
+ {
+ let path_condition_x_pos = img_width/2.0 - (TextToPrint::char_count(&path_condition_ttp) as f32)*FONT_WIDTH/4.0;
+ draw_colored_text(&mut image,&path_condition_ttp, path_condition_x_pos,MARGIN);
+ }
+
+ // Draw Lifelines
+ draw_lifelines(&mut image, &lf_x_widths, inner_height, gen_ctx, exe_ctx, init_lf_interpretations);
+
+ // Draw Fragments
+ let mut nest_shift : u32 = 1; // shift to display nested fragments
+ let mut yshift : u32 = 5 + ((additional_y_space_for_context*2) as u32);
+
+ draw_interaction_rec(&mut image, gen_ctx, exe_ctx, interaction, &lf_x_widths, &mut texts_to_print,&mut nest_shift, &mut yshift);
+
+ match multi_trace_txttoprint {
+ None => {},
+ Some( (mt_ttp,mt_print_width) ) => {
+ let mut yshift : u32 = 2;
+ for text in mt_ttp {
+ let msg_x_pos = img_width - mt_print_width - MARGIN/2.0;
+ let msg_y_pos = MARGIN + (yshift as f32)*VERTICAL_SIZE;
+ draw_colored_text(&mut image,&text,msg_x_pos,msg_y_pos);
+ yshift = yshift +2;
+ }
+ }
+ }
+
+ image.save(path).unwrap();
+}
\ No newline at end of file
diff --git a/src/rendering/custom_draw/seqdiag/lf_coords.rs b/src/rendering/custom_draw/seqdiag/lf_coords.rs
new file mode 100644
index 0000000..2ebbb2e
--- /dev/null
+++ b/src/rendering/custom_draw/seqdiag/lf_coords.rs
@@ -0,0 +1,20 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub struct DrawingLifelineCoords {
+ pub x_start : f32,
+ pub x_span_outer : f32,
+ pub x_span_inner : f32,
+ pub x_middle : f32
+}
\ No newline at end of file
diff --git a/src/rendering/custom_draw/seqdiag/mod.rs b/src/rendering/custom_draw/seqdiag/mod.rs
new file mode 100644
index 0000000..88e6e5e
--- /dev/null
+++ b/src/rendering/custom_draw/seqdiag/mod.rs
@@ -0,0 +1,22 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+mod dimensions_tools;
+mod lf_coords;
+mod action;
+mod img_content;
+mod img_frame;
+mod recursive_frag;
+pub mod interaction;
diff --git a/src/rendering/custom_draw/seqdiag/recursive_frag.rs b/src/rendering/custom_draw/seqdiag/recursive_frag.rs
new file mode 100644
index 0000000..a923770
--- /dev/null
+++ b/src/rendering/custom_draw/seqdiag/recursive_frag.rs
@@ -0,0 +1,59 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use crate::core::syntax::interaction::Interaction;
+
+
+pub fn get_recursive_alt_frags(interaction : &Interaction) -> Vec<&Interaction> {
+ let mut frags : Vec<&Interaction> = Vec::new();
+ match interaction {
+ &Interaction::Alt(ref i1, ref i2) => {
+ frags.extend( get_recursive_alt_frags(i1));
+ frags.extend( get_recursive_alt_frags(i2));
+ },
+ _ => {
+ frags.push(interaction);
+ }
+ }
+ return frags;
+}
+
+pub fn get_recursive_par_frags(interaction : &Interaction) -> Vec<&Interaction> {
+ let mut frags : Vec<&Interaction> = Vec::new();
+ match interaction {
+ &Interaction::Par(ref i1, ref i2) => {
+ frags.extend( get_recursive_par_frags(i1));
+ frags.extend( get_recursive_par_frags(i2));
+ },
+ _ => {
+ frags.push(interaction);
+ }
+ }
+ return frags;
+}
+
+pub fn get_recursive_strict_frags(interaction : &Interaction) -> Vec<&Interaction> {
+ let mut frags : Vec<&Interaction> = Vec::new();
+ match interaction {
+ &Interaction::Strict(ref i1, ref i2) => {
+ frags.extend( get_recursive_strict_frags(i1));
+ frags.extend( get_recursive_strict_frags(i2));
+ },
+ _ => {
+ frags.push(interaction);
+ }
+ }
+ return frags;
+}
+
diff --git a/src/rendering/custom_draw/utils/arrow_heads.rs b/src/rendering/custom_draw/utils/arrow_heads.rs
new file mode 100644
index 0000000..1c9a1e0
--- /dev/null
+++ b/src/rendering/custom_draw/utils/arrow_heads.rs
@@ -0,0 +1,82 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+
+// **********
+
+use image::{Rgb,RgbImage};
+use imageproc::drawing::{draw_line_segment_mut};
+use imageproc::drawing::draw_cubic_bezier_curve_mut;
+
+// **********
+
+use crate::rendering::sd_drawing_conf::ARROW_HEAD_LENGTH;
+
+// **********
+
+pub fn draw_double_half_ellipsis_leftward(image : &mut RgbImage, x_pos : f32, y_pos : f32, my_color : Rgb<u8>) {
+ draw_cubic_bezier_curve_mut(image,
+ (x_pos - 0.5*(ARROW_HEAD_LENGTH as f32), y_pos - 0.5*(ARROW_HEAD_LENGTH as f32)),
+ (x_pos - 0.5*(ARROW_HEAD_LENGTH as f32), y_pos + 0.5*(ARROW_HEAD_LENGTH as f32)),
+ (x_pos + 1.5*(ARROW_HEAD_LENGTH as f32), y_pos - 0.5*(ARROW_HEAD_LENGTH as f32)),
+ (x_pos + 1.5*(ARROW_HEAD_LENGTH as f32), y_pos + 0.5*(ARROW_HEAD_LENGTH as f32)),
+ my_color);
+ draw_cubic_bezier_curve_mut(image,
+ (x_pos - 0.5*(ARROW_HEAD_LENGTH as f32), y_pos - 0.25*(ARROW_HEAD_LENGTH as f32)),
+ (x_pos - 0.5*(ARROW_HEAD_LENGTH as f32), y_pos + 0.25*(ARROW_HEAD_LENGTH as f32)),
+ (x_pos + 1.0*(ARROW_HEAD_LENGTH as f32), y_pos - 0.25*(ARROW_HEAD_LENGTH as f32)),
+ (x_pos + 1.0*(ARROW_HEAD_LENGTH as f32), y_pos + 0.25*(ARROW_HEAD_LENGTH as f32)),
+ my_color);
+}
+
+pub fn draw_double_half_ellipsis_rightward(image : &mut RgbImage, x_pos : f32, y_pos : f32, my_color : Rgb<u8>) {
+ draw_cubic_bezier_curve_mut(image,
+ (x_pos + 0.5*(ARROW_HEAD_LENGTH as f32), y_pos - 0.5*(ARROW_HEAD_LENGTH as f32)),
+ (x_pos + 0.5*(ARROW_HEAD_LENGTH as f32), y_pos + 0.5*(ARROW_HEAD_LENGTH as f32)),
+ (x_pos - 1.5*(ARROW_HEAD_LENGTH as f32), y_pos - 0.5*(ARROW_HEAD_LENGTH as f32)),
+ (x_pos - 1.5*(ARROW_HEAD_LENGTH as f32), y_pos + 0.5*(ARROW_HEAD_LENGTH as f32)),
+ my_color);
+ draw_cubic_bezier_curve_mut(image,
+ (x_pos + 0.5*(ARROW_HEAD_LENGTH as f32), y_pos - 0.25*(ARROW_HEAD_LENGTH as f32)),
+ (x_pos + 0.5*(ARROW_HEAD_LENGTH as f32), y_pos + 0.25*(ARROW_HEAD_LENGTH as f32)),
+ (x_pos - 1.0*(ARROW_HEAD_LENGTH as f32), y_pos - 0.25*(ARROW_HEAD_LENGTH as f32)),
+ (x_pos - 1.0*(ARROW_HEAD_LENGTH as f32), y_pos + 0.25*(ARROW_HEAD_LENGTH as f32)),
+ my_color);
+}
+
+pub fn draw_arrowhead_rightward(image : &mut RgbImage, x_pos : f32, y_pos : f32, my_color : Rgb<u8>) {
+ draw_line_segment_mut(image,
+ (x_pos, y_pos),
+ (x_pos - (ARROW_HEAD_LENGTH as f32), y_pos - (ARROW_HEAD_LENGTH as f32)),
+ my_color);
+ draw_line_segment_mut(image,
+ (x_pos, y_pos),
+ (x_pos - (ARROW_HEAD_LENGTH as f32), y_pos + (ARROW_HEAD_LENGTH as f32)),
+ my_color);
+}
+
+pub fn draw_arrowhead_leftward(image : &mut RgbImage, x_pos : f32, y_pos : f32, my_color : Rgb<u8>) {
+ draw_line_segment_mut(image,
+ (x_pos, y_pos),
+ (x_pos + (ARROW_HEAD_LENGTH as f32), y_pos - (ARROW_HEAD_LENGTH as f32)),
+ my_color);
+ draw_line_segment_mut(image,
+ (x_pos, y_pos),
+ (x_pos + (ARROW_HEAD_LENGTH as f32), y_pos + (ARROW_HEAD_LENGTH as f32)),
+ my_color);
+}
+
+// **********
+
diff --git a/src/rendering/custom_draw/utils/colored_text.rs b/src/rendering/custom_draw/utils/colored_text.rs
new file mode 100644
index 0000000..ef79fea
--- /dev/null
+++ b/src/rendering/custom_draw/utils/colored_text.rs
@@ -0,0 +1,45 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use image::{Rgb, RgbImage};
+use rusttype::{FontCollection, Scale};
+use imageproc::drawing::draw_text_mut;
+
+use crate::rendering::textual::convention::*;
+use crate::rendering::sd_drawing_conf::*;
+use crate::rendering::textual::colored::colored_text::*;
+
+pub fn draw_colored_text(image : &mut RgbImage,
+ to_print : &Vec<TextToPrint>,
+ msg_x_pos : f32,
+ msg_y_pos : f32) {
+ let font = FontCollection::from_bytes(HIBOU_GRAPHIC_FONT).unwrap().into_font().unwrap();
+ let scale = Scale { x: FONT_WIDTH, y: FONT_HEIGHT };
+
+ // ***
+ let mut char_count : u32 = 0;
+ for txt_to_print in to_print {
+ let mut my_text : String = (0..char_count).map(|_| " ").collect::<String>();
+ my_text.push_str( &txt_to_print.text );
+ draw_text_mut(image,
+ txt_to_print.color,
+ msg_x_pos as u32,
+ (msg_y_pos - (VERTICAL_SIZE as f32)/2.0) as u32,
+ scale,
+ &font,
+ &my_text
+ );
+ char_count = char_count + txt_to_print.text.chars().count() as u32;
+ }
+}
\ No newline at end of file
diff --git a/src/rendering/custom_draw/utils/mod.rs b/src/rendering/custom_draw/utils/mod.rs
new file mode 100644
index 0000000..5c756b3
--- /dev/null
+++ b/src/rendering/custom_draw/utils/mod.rs
@@ -0,0 +1,16 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod colored_text;
+pub mod arrow_heads;
\ No newline at end of file
diff --git a/src/rendering/graphviz/common.rs b/src/rendering/graphviz/common.rs
new file mode 100644
index 0000000..bae3107
--- /dev/null
+++ b/src/rendering/graphviz/common.rs
@@ -0,0 +1,163 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub trait DotTranslatable {
+ fn to_dot_string(&self) -> String;
+}
+
+
+
+
+use strum::AsStaticRef;
+
+#[derive(AsStaticStr,Eq,PartialEq,Clone)]
+pub enum GraphvizColor {
+ aliceblue,antiquewhite,antiquewhite1,antiquewhite2,antiquewhite3,
+ antiquewhite4,aquamarine,aquamarine1,aquamarine2,aquamarine3,
+ aquamarine4,azure,azure1,azure2,azure3,
+ azure4,beige,bisque,bisque1,bisque2,
+ bisque3,bisque4,black,blanchedalmond,blue,
+ blue1,blue2,blue3,blue4,blueviolet,
+ brown,brown1,brown2,brown3,brown4,
+ burlywood,burlywood1,burlywood2,burlywood3,burlywood4,
+ cadetblue,cadetblue1,cadetblue2,cadetblue3,cadetblue4,
+ chartreuse,chartreuse1,chartreuse2,chartreuse3,chartreuse4,
+ chocolate,chocolate1,chocolate2,chocolate3,chocolate4,
+ coral,coral1,coral2,coral3,coral4,
+ cornflowerblue,cornsilk,cornsilk1,cornsilk2,cornsilk3,
+ cornsilk4,crimson,cyan,cyan1,cyan2,
+ cyan3,cyan4,darkgoldenrod,darkgoldenrod1,darkgoldenrod2,
+ darkgoldenrod3,darkgoldenrod4,darkgreen,darkkhaki,darkolivegreen,
+ darkolivegreen1,darkolivegreen2,darkolivegreen3,darkolivegreen4,darkorange,
+ darkorange1,darkorange2,darkorange3,darkorange4,darkorchid,
+ darkorchid1,darkorchid2,darkorchid3,darkorchid4,darksalmon,
+ darkseagreen,darkseagreen1,darkseagreen2,darkseagreen3,darkseagreen4,
+ darkslateblue,darkslategray,darkslategray1,darkslategray2,darkslategray3,
+ darkslategray4,darkslategrey,darkturquoise,darkviolet,deeppink,
+ deeppink1,deeppink2,deeppink3,deeppink4,deepskyblue,
+ deepskyblue1,deepskyblue2,deepskyblue3,deepskyblue4,dimgray,
+ dimgrey,dodgerblue,dodgerblue1,dodgerblue2,dodgerblue3,
+ dodgerblue4,firebrick,firebrick1,firebrick2,firebrick3,
+ firebrick4,floralwhite,forestgreen,gainsboro,ghostwhite,
+ gold,gold1,gold2,gold3,gold4,
+ goldenrod,goldenrod1,goldenrod2,goldenrod3,goldenrod4,
+ gray,gray0,gray1,gray10,gray100,
+ gray11,gray12,gray13,gray14,gray15,
+ gray16,gray17,gray18,gray19,gray2,
+ gray20,gray21,gray22,gray23,gray24,
+ gray25,gray26,gray27,gray28,gray29,
+ gray3,gray30,gray31,gray32,gray33,
+ gray34,gray35,gray36,gray37,gray38,
+ gray39,gray4,gray40,gray41,gray42,
+ gray43,gray44,gray45,gray46,gray47,
+ gray48,gray49,gray5,gray50,gray51,
+ gray52,gray53,gray54,gray55,gray56,
+ gray57,gray58,gray59,gray6,gray60,
+ gray61,gray62,gray63,gray64,gray65,
+ gray66,gray67,gray68,gray69,gray7,
+ gray70,gray71,gray72,gray73,gray74,
+ gray75,gray76,gray77,gray78,gray79,
+ gray8,gray80,gray81,gray82,gray83,
+ gray84,gray85,gray86,gray87,gray88,
+ gray89,gray9,gray90,gray91,gray92,
+ gray93,gray94,gray95,gray96,gray97,
+ gray98,gray99,green,green1,green2,
+ green3,green4,greenyellow,grey,grey0,
+ grey1,grey10,grey100,grey11,grey12,
+ grey13,grey14,grey15,grey16,grey17,
+ grey18,grey19,grey2,grey20,grey21,
+ grey22,grey23,grey24,grey25,grey26,
+ grey27,grey28,grey29,grey3,grey30,
+ grey31,grey32,grey33,grey34,grey35,
+ grey36,grey37,grey38,grey39,grey4,
+ grey40,grey41,grey42,grey43,grey44,
+ grey45,grey46,grey47,grey48,grey49,
+ grey5,grey50,grey51,grey52,grey53,
+ grey54,grey55,grey56,grey57,grey58,
+ grey59,grey6,grey60,grey61,grey62,
+ grey63,grey64,grey65,grey66,grey67,
+ grey68,grey69,grey7,grey70,grey71,
+ grey72,grey73,grey74,grey75,grey76,
+ grey77,grey78,grey79,grey8,grey80,
+ grey81,grey82,grey83,grey84,grey85,
+ grey86,grey87,grey88,grey89,grey9,
+ grey90,grey91,grey92,grey93,grey94,
+ grey95,grey96,grey97,grey98,grey99,
+ honeydew,honeydew1,honeydew2,honeydew3,honeydew4,
+ hotpink,hotpink1,hotpink2,hotpink3,hotpink4,
+ indianred,indianred1,indianred2,indianred3,indianred4,
+ indigo,invis,ivory,ivory1,ivory2,
+ ivory3,ivory4,khaki,khaki1,khaki2,
+ khaki3,khaki4,lavender,lavenderblush,lavenderblush1,
+ lavenderblush2,lavenderblush3,lavenderblush4,lawngreen,lemonchiffon,
+ lemonchiffon1,lemonchiffon2,lemonchiffon3,lemonchiffon4,lightblue,
+ lightblue1,lightblue2,lightblue3,lightblue4,lightcoral,
+ lightcyan,lightcyan1,lightcyan2,lightcyan3,lightcyan4,
+ lightgoldenrod,lightgoldenrod1,lightgoldenrod2,lightgoldenrod3,lightgoldenrod4,
+ lightgoldenrodyellow,lightgray,lightgrey,lightpink,lightpink1,
+ lightpink2,lightpink3,lightpink4,lightsalmon,lightsalmon1,
+ lightsalmon2,lightsalmon3,lightsalmon4,lightseagreen,lightskyblue,
+ lightskyblue1,lightskyblue2,lightskyblue3,lightskyblue4,lightslateblue,
+ lightslategray,lightslategrey,lightsteelblue,lightsteelblue1,lightsteelblue2,
+ lightsteelblue3,lightsteelblue4,lightyellow,lightyellow1,lightyellow2,
+ lightyellow3,lightyellow4,limegreen,linen,magenta,
+ magenta1,magenta2,magenta3,magenta4,maroon,
+ maroon1,maroon2,maroon3,maroon4,mediumaquamarine,
+ mediumblue,mediumorchid,mediumorchid1,mediumorchid2,mediumorchid3,
+ mediumorchid4,mediumpurple,mediumpurple1,mediumpurple2,mediumpurple3,
+ mediumpurple4,mediumseagreen,mediumslateblue,mediumspringgreen,mediumturquoise,
+ mediumvioletred,midnightblue,mintcream,mistyrose,mistyrose1,
+ mistyrose2,mistyrose3,mistyrose4,moccasin,navajowhite,
+ navajowhite1,navajowhite2,navajowhite3,navajowhite4,navy,
+ navyblue,none,oldlace,olivedrab,olivedrab1,
+ olivedrab2,olivedrab3,olivedrab4,orange,orange1,
+ orange2,orange3,orange4,orangered,orangered1,
+ orangered2,orangered3,orangered4,orchid,orchid1,
+ orchid2,orchid3,orchid4,palegoldenrod,palegreen,
+ palegreen1,palegreen2,palegreen3,palegreen4,paleturquoise,
+ paleturquoise1,paleturquoise2,paleturquoise3,paleturquoise4,palevioletred,
+ palevioletred1,palevioletred2,palevioletred3,palevioletred4,papayawhip,
+ peachpuff,peachpuff1,peachpuff2,peachpuff3,peachpuff4,
+ peru,pink,pink1,pink2,pink3,
+ pink4,plum,plum1,plum2,plum3,
+ plum4,powderblue,purple,purple1,purple2,
+ purple3,purple4,red,red1,red2,
+ red3,red4,rosybrown,rosybrown1,rosybrown2,
+ rosybrown3,rosybrown4,royalblue,royalblue1,royalblue2,
+ royalblue3,royalblue4,saddlebrown,salmon,salmon1,
+ salmon2,salmon3,salmon4,sandybrown,seagreen,
+ seagreen1,seagreen2,seagreen3,seagreen4,seashell,
+ seashell1,seashell2,seashell3,seashell4,sienna,
+ sienna1,sienna2,sienna3,sienna4,skyblue,
+ skyblue1,skyblue2,skyblue3,skyblue4,slateblue,
+ slateblue1,slateblue2,slateblue3,slateblue4,slategray,
+ slategray1,slategray2,slategray3,slategray4,slategrey,
+ snow,snow1,snow2,snow3,snow4,
+ springgreen,springgreen1,springgreen2,springgreen3,springgreen4,
+ steelblue,steelblue1,steelblue2,steelblue3,steelblue4,
+ tan,tan1,tan2,tan3,tan4,
+ thistle,thistle1,thistle2,thistle3,thistle4,
+ tomato,tomato1,tomato2,tomato3,tomato4,
+ transparent,turquoise,turquoise1,turquoise2,turquoise3,
+ turquoise4,violet,violetred,violetred1,violetred2,
+ violetred3,violetred4,wheat,wheat1,wheat2,
+ wheat3,wheat4,white,whitesmoke,yellow,
+ yellow1,yellow2,yellow3,yellow4,yellowgreen
+}
+
+impl DotTranslatable for GraphvizColor {
+ fn to_dot_string(&self) -> String {
+ return self.as_static().to_string().to_lowercase();
+ }
+}
diff --git a/src/rendering/graphviz/edge_style.rs b/src/rendering/graphviz/edge_style.rs
new file mode 100644
index 0000000..e39fa19
--- /dev/null
+++ b/src/rendering/graphviz/edge_style.rs
@@ -0,0 +1,211 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+use crate::rendering::graphviz::common::{DotTranslatable,GraphvizColor};
+
+
+pub enum GvArrowHeadFill {
+ Open,
+ Filled,
+}
+
+impl DotTranslatable for GvArrowHeadFill {
+ fn to_dot_string(&self) -> String {
+ match self {
+ &GvArrowHeadFill::Open => "o".to_string(),
+ &GvArrowHeadFill::Filled => "".to_string(),
+ }
+ }
+}
+
+pub enum GvArrowHeadSide {
+ Left,
+ Right,
+ Both,
+}
+
+impl DotTranslatable for GvArrowHeadSide {
+ fn to_dot_string(&self) -> String {
+ match self {
+ &GvArrowHeadSide::Left => "l".to_string(),
+ &GvArrowHeadSide::Right => "r".to_string(),
+ &GvArrowHeadSide::Both => "".to_string(),
+ }
+ }
+}
+
+
+pub enum GvArrowHeadStyle {
+ /// No arrow will be displayed
+ NoArrow,
+ /// Arrow that ends in a triangle. Basically a normal arrow.
+ /// NOTE: there is error in official documentation, this supports both fill and side clipping
+ Normal(GvArrowHeadFill, GvArrowHeadSide),
+ /// Arrow ending in a small square box
+ Box(GvArrowHeadFill, GvArrowHeadSide),
+ /// Arrow ending in a three branching lines also called crow's foot
+ Crow(GvArrowHeadSide),
+ /// Arrow ending in a curve
+ Curve(GvArrowHeadSide),
+ /// Arrow ending in an inverted curve
+ ICurve(GvArrowHeadFill, GvArrowHeadSide),
+ /// Arrow ending in an diamond shaped rectangular shape.
+ Diamond(GvArrowHeadFill, GvArrowHeadSide),
+ /// Arrow ending in a circle.
+ Dot(GvArrowHeadFill),
+ /// Arrow ending in an inverted triangle.
+ Inv(GvArrowHeadFill, GvArrowHeadSide),
+ /// Arrow ending with a T shaped arrow.
+ Tee(GvArrowHeadSide),
+ /// Arrow ending with a V shaped arrow.
+ Vee(GvArrowHeadSide),
+}
+impl DotTranslatable for GvArrowHeadStyle {
+
+ fn to_dot_string(&self) -> String {
+ let mut res = String::new();
+ match self {
+ GvArrowHeadStyle::Box(fill, side) | GvArrowHeadStyle::ICurve(fill, side)| GvArrowHeadStyle::Diamond(fill, side) |
+ GvArrowHeadStyle::Inv(fill, side) | GvArrowHeadStyle::Normal(fill, side)=> {
+ res.push_str(&fill.to_dot_string());
+ match side {
+ GvArrowHeadSide::Left | GvArrowHeadSide::Right => res.push_str(&side.to_dot_string()),
+ GvArrowHeadSide::Both => {},
+ };
+ },
+ GvArrowHeadStyle::Dot(fill) => res.push_str(&fill.to_dot_string()),
+ GvArrowHeadStyle::Crow(side) | GvArrowHeadStyle::Curve(side) | GvArrowHeadStyle::Tee(side)
+ | GvArrowHeadStyle::Vee(side) => {
+ match side {
+ GvArrowHeadSide::Left | GvArrowHeadSide::Right => res.push_str(&side.to_dot_string()),
+ GvArrowHeadSide::Both => {},
+ }
+ }
+ GvArrowHeadStyle::NoArrow => {},
+ };
+ match self {
+ GvArrowHeadStyle::NoArrow => res.push_str("none"),
+ GvArrowHeadStyle::Normal(_, _) => res.push_str("normal"),
+ GvArrowHeadStyle::Box(_, _) => res.push_str("box"),
+ GvArrowHeadStyle::Crow(_) => res.push_str("crow"),
+ GvArrowHeadStyle::Curve(_) => res.push_str("curve"),
+ GvArrowHeadStyle::ICurve(_, _) => res.push_str("icurve"),
+ GvArrowHeadStyle::Diamond(_, _) => res.push_str("diamond"),
+ GvArrowHeadStyle::Dot(_) => res.push_str("dot"),
+ GvArrowHeadStyle::Inv(_, _) => res.push_str("inv"),
+ GvArrowHeadStyle::Tee(_) => res.push_str("tee"),
+ GvArrowHeadStyle::Vee(_) => res.push_str("vee"),
+ };
+ res
+ }
+}
+
+
+pub enum GvEdgeLineStyle {
+ Solid,
+ Dashed,
+ Dotted,
+ Bold
+}
+
+impl DotTranslatable for GvEdgeLineStyle {
+ fn to_dot_string(&self) -> String {
+ match self {
+ &GvEdgeLineStyle::Solid => "solid".to_string(),
+ &GvEdgeLineStyle::Dashed => "dashed".to_string(),
+ &GvEdgeLineStyle::Dotted => "dotted".to_string(),
+ &GvEdgeLineStyle::Bold => "bold".to_string()
+ }
+ }
+}
+
+
+
+pub enum GraphvizEdgeStyleItem {
+ LineStyle(GvEdgeLineStyle),
+ Label(String),
+ Head(GvArrowHeadStyle),
+ Tail(GvArrowHeadStyle),
+ Color(GraphvizColor),
+ FontColor(GraphvizColor),
+ ArrowSize(u32),
+ FontSize(u32)
+}
+
+impl DotTranslatable for GraphvizEdgeStyleItem {
+ fn to_dot_string(&self) -> String {
+ let mut res = String::new();
+ match self {
+ GraphvizEdgeStyleItem::LineStyle(ref line_style) => {
+ res.push_str("style=");
+ res.push_str(&(line_style.to_dot_string()));
+ },
+ GraphvizEdgeStyleItem::Label(ref label) => {
+ res.push_str("label=\"");
+ res.push_str(&label);
+ res.push_str("\"");
+ },
+ GraphvizEdgeStyleItem::Head(arrow_head_style) => {
+ res.push_str("arrowhead=");
+ res.push_str(&(arrow_head_style.to_dot_string()));
+ },
+ GraphvizEdgeStyleItem::Tail(arrow_head_style) => {
+ res.push_str("arrowtail=");
+ res.push_str(&(arrow_head_style.to_dot_string()));
+ },
+ GraphvizEdgeStyleItem::Color(graphviz_color) => {
+ res.push_str("color=");
+ res.push_str(&(graphviz_color.to_dot_string()));
+ },
+ GraphvizEdgeStyleItem::FontColor(graphviz_color) => {
+ res.push_str("fontcolor=");
+ res.push_str(&(graphviz_color.to_dot_string()));
+ },
+ GraphvizEdgeStyleItem::ArrowSize(size) => {
+ res.push_str("arrowsize=");
+ res.push_str(&(size.to_string()));
+ },
+ GraphvizEdgeStyleItem::FontSize(size) => {
+ res.push_str("fontsize=");
+ res.push_str(&(size.to_string()));
+ }
+ }
+ return res;
+ }
+}
+
+pub type GraphvizEdgeStyle = Vec<GraphvizEdgeStyleItem>;
+
+impl DotTranslatable for GraphvizEdgeStyle {
+ fn to_dot_string(&self) -> String {
+ if self.len()==0 {
+ return "".to_string();
+ }
+ let mut res = String::new();
+ let mut first : bool = true;
+ res.push_str("[");
+ for item in self {
+ if first {
+ first = false;
+ } else {
+ res.push_str(",");
+ }
+ res.push_str(&(item.to_dot_string()) );
+ }
+ res.push_str("]");
+ return res;
+ }
+}
+
diff --git a/src/rendering/graphviz/graph.rs b/src/rendering/graphviz/graph.rs
new file mode 100644
index 0000000..0db6574
--- /dev/null
+++ b/src/rendering/graphviz/graph.rs
@@ -0,0 +1,76 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+use crate::rendering::graphviz::node_style::GraphvizNodeStyle;
+use crate::rendering::graphviz::edge_style::GraphvizEdgeStyle;
+use crate::rendering::graphviz::common::DotTranslatable;
+
+pub struct GraphVizNode {
+ pub id : String,
+ pub style : GraphvizNodeStyle
+}
+
+
+impl DotTranslatable for GraphVizNode {
+ fn to_dot_string(&self) -> String {
+ let mut res = String::new();
+ res.push_str(&(self.id));
+ res.push_str(&(self.style.to_dot_string()));
+ res.push_str(";");
+ return res;
+ }
+}
+
+
+pub struct GraphVizEdge {
+ pub origin_id : String,
+ pub target_id : String,
+ pub style : GraphvizEdgeStyle
+}
+
+impl DotTranslatable for GraphVizEdge {
+ fn to_dot_string(&self) -> String {
+ let mut res = String::new();
+ res.push_str(&(self.origin_id));
+ res.push_str("->");
+ res.push_str(&(self.target_id));
+ res.push_str(& self.style.to_dot_string() );
+ res.push_str(";");
+ return res;
+ }
+}
+
+
+pub struct GraphVizDiGraph {
+ pub nodes : Vec<GraphVizNode>,
+ pub edges : Vec<GraphVizEdge>
+}
+
+impl DotTranslatable for GraphVizDiGraph {
+ fn to_dot_string(&self) -> String {
+ let mut res = String::new();
+ res.push_str("digraph G {");
+ for node in &self.nodes {
+ res.push_str("\n\t");
+ res.push_str(& node.to_dot_string() );
+ }
+ for edge in &self.edges {
+ res.push_str("\n\t");
+ res.push_str(& edge.to_dot_string() );
+ }
+ res.push_str("\n}");
+ return res;
+ }
+}
\ No newline at end of file
diff --git a/src/rendering/graphviz/mod.rs b/src/rendering/graphviz/mod.rs
new file mode 100644
index 0000000..9a3e4d1
--- /dev/null
+++ b/src/rendering/graphviz/mod.rs
@@ -0,0 +1,19 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+pub mod common;
+pub mod edge_style;
+pub mod graph;
+pub mod node_style;
\ No newline at end of file
diff --git a/src/rendering/graphviz/node_style.rs b/src/rendering/graphviz/node_style.rs
new file mode 100644
index 0000000..cc44fe0
--- /dev/null
+++ b/src/rendering/graphviz/node_style.rs
@@ -0,0 +1,161 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+use strum::AsStaticRef;
+
+use crate::rendering::graphviz::common::{DotTranslatable,GraphvizColor};
+
+
+
+
+#[derive(AsStaticStr)]
+pub enum GvNodeStyleKind {
+ Solid,
+ Dashed,
+ Dotted,
+ Bold,
+ Rounded,
+ Diagonals,
+ Filled,
+ Striped,
+ Wedged
+}
+
+impl DotTranslatable for GvNodeStyleKind {
+ fn to_dot_string(&self) -> String {
+ return self.as_static().to_string().to_lowercase();
+ }
+}
+
+pub type GvNodeStyle = Vec<GvNodeStyleKind>;
+
+impl DotTranslatable for GvNodeStyle {
+ fn to_dot_string(&self) -> String {
+ let mut dot_str = "\"".to_string();
+ let mut rem_styles = self.len();
+ for sty_kind in self {
+ dot_str.push_str( &sty_kind.to_dot_string() );
+ rem_styles = rem_styles -1;
+ if rem_styles > 0 {
+ dot_str.push_str( "," );
+ }
+ }
+ dot_str.push_str( "\"" );
+ return dot_str;
+ }
+}
+
+
+#[derive(AsStaticStr)]
+pub enum GvNodeShape {
+ Ellipse,
+ Circle,
+ Triangle,
+ Diamond,
+ Trapezium,
+ Parallelogram,
+ House,
+ Pentagon,
+ Hexagon,
+ Septagon,
+ Octagon,
+ Rectangle,
+ Square,
+ InvTriangle,
+ InvTrapezium,
+ InvHouse,
+ Star
+}
+
+impl DotTranslatable for GvNodeShape {
+ fn to_dot_string(&self) -> String {
+ return self.as_static().to_string().to_lowercase();
+ }
+}
+
+
+
+
+
+pub enum GraphvizNodeStyleItem {
+ Style(GvNodeStyle),
+ Shape(GvNodeShape),
+ Label(String),
+ Image(String),
+ Color(GraphvizColor),
+ FontColor(GraphvizColor),
+ FontSize(u32),
+ FontName(String)
+}
+
+impl DotTranslatable for GraphvizNodeStyleItem {
+ fn to_dot_string(&self) -> String {
+ let mut res = String::new();
+ match self {
+ GraphvizNodeStyleItem::Style(node_style) => {
+ res.push_str("style=");
+ res.push_str(&(node_style.to_dot_string()));
+ },
+ GraphvizNodeStyleItem::Shape(node_shape) => {
+ res.push_str("shape=");
+ res.push_str(&(node_shape.to_dot_string()));
+ },
+ GraphvizNodeStyleItem::Label(label) => {
+ res.push_str(&format!("label=\"{}\"",label));
+ },
+ GraphvizNodeStyleItem::Image(imgpath) => {
+ res.push_str(&format!("image=\"{}\"",imgpath));
+ },
+ GraphvizNodeStyleItem::Color(graphviz_color) => {
+ res.push_str("color=");
+ res.push_str(&(graphviz_color.to_dot_string()));
+ },
+ GraphvizNodeStyleItem::FontColor(graphviz_color) => {
+ res.push_str("fontcolor=");
+ res.push_str(&(graphviz_color.to_dot_string()));
+ },
+ GraphvizNodeStyleItem::FontSize(size) => {
+ res.push_str("fontsize=");
+ res.push_str(&(size.to_string()));
+ },GraphvizNodeStyleItem::FontName(fname) => {
+ res.push_str(&format!("fontname=\"{}\"",fname));
+ }
+ }
+ return res;
+ }
+}
+
+pub type GraphvizNodeStyle = Vec<GraphvizNodeStyleItem>;
+
+impl DotTranslatable for GraphvizNodeStyle {
+ fn to_dot_string(&self) -> String {
+ if self.len()==0 {
+ return "".to_string();
+ }
+ let mut res = String::new();
+ let mut first : bool = true;
+ res.push_str("[");
+ for item in self {
+ if first {
+ first = false;
+ } else {
+ res.push_str(",");
+ }
+ res.push_str(&(item.to_dot_string()) );
+ }
+ res.push_str("]");
+ return res;
+ }
+}
diff --git a/src/rendering/hibou_color_palette.rs b/src/rendering/hibou_color_palette.rs
new file mode 100644
index 0000000..38fb58a
--- /dev/null
+++ b/src/rendering/hibou_color_palette.rs
@@ -0,0 +1,101 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+/*
+
+HIBOU Color Palette
+My color picks for a palette with:
+ - a constant Lightness L
+ - a constant Saturation S
+in the HSL representation of colors
+
+All colors have :
+ - a lightness of :
+ + 20 for the "Dark" version
+ + 30 for the "Standard" version
+ + 50 for the "Light" version
+ + 65 for the "Bright" version
+ - a saturation of :
+ + 70 for the "Dark" version
+ + 70 for the "Standard" version
+ + 70 for the "Light" version
+ + 90 for the "Bright" version
+
+Different hues were selected :
+ - 0 for "Red"
+ - 30 for "Orange"
+ - 60 for "Yellow"
+ - 120 for "Green"
+ - 180 for "Cyan"
+ - 240 for "Blue"
+ - 280 for "Purple"
+ - 310 for "Pink"
+
+For use with image::Rgb from the "image" crate
+
+*/
+
+pub const HCP_White : [u8;3] = [255u8, 255u8, 255u8];
+pub const HCP_Black : [u8;3] = [0u8, 0u8, 0u8];
+
+pub const HCP_DarkRed : [u8;3] = [86u8, 15u8, 15u8];
+pub const HCP_StandardRed : [u8;3] = [130u8, 22u8, 22u8];
+pub const HCP_LightRed : [u8;3] = [216u8, 38u8, 38u8];
+pub const HCP_BrightRed : [u8;3] = [246u8, 85u8, 85u8];
+pub const HCP_DarkOrange : [u8;3] = [86u8, 51u8, 15u8];
+pub const HCP_StandardOrange : [u8;3] = [130u8, 76u8, 22u8];
+pub const HCP_LightOrange : [u8;3] = [216u8, 127u8, 38u8];
+pub const HCP_BrightOrange : [u8;3] = [246u8, 165u8, 85u8];
+pub const HCP_DarkYellow : [u8;3] = [86u8, 86u8, 15u8];
+pub const HCP_StandardYellow : [u8;3] = [130u8, 130u8, 22u8];
+pub const HCP_LightYellow : [u8;3] = [216u8, 216u8, 38u8];
+pub const HCP_BrightYellow : [u8;3] = [246u8, 246u8, 85u8];
+pub const HCP_DarkGreen : [u8;3] = [15u8, 86u8, 15u8];
+pub const HCP_StandardGreen : [u8;3] = [22u8, 130u8, 22u8];
+pub const HCP_LightGreen : [u8;3] = [38u8, 216u8, 38u8];
+pub const HCP_BrightGreen : [u8;3] = [85u8, 246u8, 85u8];
+pub const HCP_DarkCyan : [u8;3] = [15u8, 86u8, 86u8];
+pub const HCP_StandardCyan : [u8;3] = [22u8, 130u8, 130u8];
+pub const HCP_LightCyan : [u8;3] = [38u8, 216u8, 216u8];
+pub const HCP_BrightCyan : [u8;3] = [85u8, 246u8, 246u8];
+pub const HCP_DarkBlue : [u8;3] = [15u8, 15u8, 86u8];
+pub const HCP_StandardBlue : [u8;3] = [22u8, 22u8, 130u8];
+pub const HCP_LightBlue : [u8;3] = [38u8, 38u8, 216u8];
+pub const HCP_BrightBlue : [u8;3] = [85u8, 85u8, 246u8];
+pub const HCP_DarkPurple : [u8;3] = [62u8, 15u8, 86u8];
+pub const HCP_StandardPurple : [u8;3] = [94u8, 22u8, 130u8];
+pub const HCP_LightPurple : [u8;3] = [157u8, 38u8, 216u8];
+pub const HCP_BrightPurple : [u8;3] = [192u8, 85u8, 246u8];
+pub const HCP_DarkPink : [u8;3] = [86u8, 15u8, 74u8];
+pub const HCP_StandardPink : [u8;3] = [130u8, 22u8, 112u8];
+pub const HCP_LightPink : [u8;3] = [216u8, 38u8, 186u8];
+pub const HCP_BrightPink : [u8;3] = [246u8, 85u8, 219u8];
+
+pub const HCP_DarkGray : [u8;3] = [51u8, 51u8, 51u8];
+pub const HCP_StandardGray : [u8;3] = [76u8, 76u8, 76u8];
+pub const HCP_LightGray : [u8;3] = [127u8, 127u8, 127u8];
+pub const HCP_BrightGray : [u8;3] = [165u8, 165u8, 165u8];
+
+
+pub const HC_LifelineGroup : [u8;3] = HCP_StandardCyan;
+pub const HC_Lifeline : [u8;3] = HCP_StandardBlue;
+pub const HC_MessageParameter : [u8;3] = HCP_StandardGreen;
+pub const HC_Message : [u8;3] = HCP_DarkGreen; //HCP_StandardGreen; HCP_StandardPurple;
+pub const HC_Grammar_Symbol : [u8;3] = HCP_Black;
+pub const HC_Concrete_Value : [u8;3] = HCP_StandardGray;
+pub const HC_Variable : [u8;3] = HCP_StandardRed;
+pub const HC_Symbol : [u8;3] = HCP_StandardOrange;
+pub const HC_NewFresh : [u8;3] = HCP_StandardPurple;
+
+//pub const HC_Concrete_Value_Secondary : [u8;3] = HCP_StandardGray;
diff --git a/src/rendering/mod.rs b/src/rendering/mod.rs
new file mode 100644
index 0000000..0cec2ce
--- /dev/null
+++ b/src/rendering/mod.rs
@@ -0,0 +1,20 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod hibou_color_palette;
+pub mod sd_drawing_conf;
+pub mod textual;
+pub mod graphviz;
+pub mod custom_draw;
+pub mod process;
diff --git a/src/rendering/process/graphic_logger.rs b/src/rendering/process/graphic_logger.rs
new file mode 100644
index 0000000..3ac73f6
--- /dev/null
+++ b/src/rendering/process/graphic_logger.rs
@@ -0,0 +1,422 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+use std::collections::HashMap;
+use std::fs;
+use std::fs::File;
+use std::io::{Read,BufReader,BufRead,BufWriter,Write};
+
+// ***
+use std::process::{Command,Output};
+
+// ***
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::position::*;
+use crate::core::syntax::interaction::Interaction;
+use crate::core::trace::AnalysableMultiTrace;
+use crate::core::syntax::action::*;
+
+
+use crate::process::log::ProcessLogger;
+use crate::rendering::textual::monochrome::position::position_to_text;
+use crate::rendering::graphviz::graph::*;
+use crate::rendering::graphviz::node_style::*;
+use crate::rendering::graphviz::edge_style::*;
+use crate::rendering::graphviz::common::*;
+use crate::rendering::custom_draw::seqdiag::interaction::draw_interaction;
+use crate::rendering::custom_draw::firing::draw_firing::{draw_firing_on_model_action,draw_firing_on_trace_against_model_action};
+use crate::process::verdicts::CoverageVerdict;
+use crate::core::trace::{TraceAction,TraceActionKind};
+
+use crate::process::hibou_process::FilterEliminationKind;
+
+use crate::rendering::process::verdict::*;
+// ***
+
+use crate::process::hibou_process::*;
+
+pub enum GraphicProcessLoggerKind {
+ svg,
+ png
+}
+
+pub struct GraphicProcessLogger {
+ log_name : String,
+ file : File,
+ kind:GraphicProcessLoggerKind
+}
+
+impl GraphicProcessLogger {
+ pub fn new(log_name : String,kind:GraphicProcessLoggerKind) -> GraphicProcessLogger {
+ let file = File::create(&format!("{:}.dot",log_name)).unwrap();
+ // ***
+ return GraphicProcessLogger{
+ log_name,
+ file,
+ kind}
+ }
+}
+
+impl ProcessLogger for GraphicProcessLogger {
+
+ fn log_verdict(&mut self,
+ parent_state_id : u32,
+ verdict : &CoverageVerdict) {
+ // ***
+ let parent_interaction_node_name = format!("i{:}", parent_state_id);
+ // ***
+ let verdict_node_name = format!("v{:}", parent_state_id);
+ // *****
+ let mut node_gv_options : GraphvizNodeStyle = Vec::new();
+ let mut tran_gv_options : GraphvizEdgeStyle = Vec::new();
+ tran_gv_options.push( GraphvizEdgeStyleItem::Head( GvArrowHeadStyle::Vee(GvArrowHeadSide::Both) ) );
+ // *****
+ node_gv_options.push( GraphvizNodeStyleItem::Label( verdict.to_string() ) );
+ // *****
+ let verdict_color = verdict.get_verdict_color();
+ node_gv_options.push( GraphvizNodeStyleItem::Color( verdict_color.clone() ) );
+ node_gv_options.push( GraphvizNodeStyleItem::FontColor( GraphvizColor::beige ) );
+ node_gv_options.push( GraphvizNodeStyleItem::FontSize( 16 ) );
+ node_gv_options.push( GraphvizNodeStyleItem::FontName( "times-bold".to_string() ) );
+ node_gv_options.push( GraphvizNodeStyleItem::Shape(GvNodeShape::Diamond) );
+ node_gv_options.push( GraphvizNodeStyleItem::Style(vec![GvNodeStyleKind::Filled]) );
+
+ tran_gv_options.push( GraphvizEdgeStyleItem::Color( verdict_color ) );
+ // *****
+ let gv_edge = GraphVizEdge{origin_id : parent_interaction_node_name.clone(), target_id : verdict_node_name.clone(), style : tran_gv_options};
+ let gv_node = GraphVizNode{id : verdict_node_name, style : node_gv_options};
+ let mut string_to_write = gv_node.to_dot_string();
+ string_to_write.push_str("\n");
+ string_to_write.push_str(&gv_edge.to_dot_string());
+ string_to_write.push_str("\n");
+ // *****
+ self.file.write( string_to_write.as_bytes() );
+ }
+
+ fn log_init(&mut self,
+ interaction : &Interaction,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ remaining_multi_trace : &Option<AnalysableMultiTrace>) {
+ // ***
+ // empties temp directory if exists
+ match fs::remove_dir_all("./temp") {
+ Ok(_) => {
+ // do nothing
+ },
+ Err(e) => {
+ // do nothing
+ }
+ }
+ // creates temp directory
+ fs::create_dir_all("./temp").unwrap();
+ // ***
+ self.file.write("digraph G {\n".as_bytes() );
+ // ***
+ // ***
+ let gv_node_path : String = format!("./temp/{:}_i1.png", self.log_name);
+ draw_interaction(&gv_node_path, interaction, gen_ctx, exe_ctx, remaining_multi_trace);
+
+ let mut node_gv_options : GraphvizNodeStyle = Vec::new();
+ node_gv_options.push( GraphvizNodeStyleItem::Label("".to_owned()) );
+ node_gv_options.push( GraphvizNodeStyleItem::Image( gv_node_path ) );
+ node_gv_options.push( GraphvizNodeStyleItem::Shape(GvNodeShape::Rectangle) );
+
+ let gv_node = GraphVizNode{id : "i1".to_owned(), style : node_gv_options};
+ let mut string_to_write = gv_node.to_dot_string();
+ string_to_write.push_str("\n");
+ self.file.write( string_to_write.as_bytes() );
+ }
+
+ fn log_term(&mut self,
+ options_as_strs : &Vec<String>) {
+
+ // *** LEGEND
+ {
+ let mut legend_str = String::new();
+ for opt_str in options_as_strs {
+ legend_str.push_str(opt_str);
+ legend_str.push_str("\\l");
+ }
+ // ***
+ let mut legend_node_gv_options : GraphvizNodeStyle = Vec::new();
+ legend_node_gv_options.push( GraphvizNodeStyleItem::Label( legend_str ) );
+ legend_node_gv_options.push( GraphvizNodeStyleItem::Shape(GvNodeShape::Rectangle) );
+ legend_node_gv_options.push( GraphvizNodeStyleItem::Style(vec![GvNodeStyleKind::Bold,GvNodeStyleKind::Rounded]) );
+ legend_node_gv_options.push( GraphvizNodeStyleItem::FontSize( 18 ) );
+ // ***
+ let legend_node = GraphVizNode{id : "legend".to_owned(), style : legend_node_gv_options};
+ let legend_as_dot_str = format!("{}\n", legend_node.to_dot_string());
+ self.file.write( legend_as_dot_str.as_bytes() );
+ }
+ // ***
+ self.file.write( "}".as_bytes() );
+ // ***
+ match self.kind {
+ GraphicProcessLoggerKind::png => {
+ match Command::new("dot")
+ .arg("-Tpng")
+ .arg(&format!("{:}.dot",self.log_name))
+ .arg("-o")
+ .arg(&format!("{:}.png",self.log_name))
+ .output() {
+ Err(e) => {
+ println!("error while calling dot -Tpng : {:?}", e);
+ }
+ Ok( output ) => {
+ if !output.status.success() {
+ println!("could not generate png graph");
+ println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
+ println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
+ }
+ }
+ }
+ },
+ GraphicProcessLoggerKind::svg => {
+ match Command::new("dot")
+ .arg("-Tsvg:cairo")
+ .arg(&format!("{:}.dot",self.log_name))
+ .arg("-o")
+ .arg(&format!("{:}.svg",self.log_name))
+ .output() {
+ Err(e) => {
+ println!("error while calling dot -Tsvg:cairo : {:?}", e);
+ }
+ Ok( output ) => {
+ if !output.status.success() {
+ println!("could not use cairo to generate svg graph with embedded interaction images...");
+ println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
+ println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
+ println!("... generating svg with external references");
+ match Command::new("dot")
+ .arg("-Tsvg")
+ .arg(&format!("{:}.dot",self.log_name))
+ .arg("-o")
+ .arg(&format!("{:}.svg",self.log_name))
+ .output() {
+ Err(e) => {
+ println!("error while calling dot -Tsvg : {:?}", e);
+ }
+ Ok( output ) => {
+ if !output.status.success() {
+ println!("could not generate svg graph with external references");
+ println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
+ println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ fn log_execution(&mut self,
+ gen_ctx : &GeneralContext,
+ parent_state_id : u32,
+ new_state_id : u32,
+ action_position : &Position,
+ trace_action : Option<&TraceAction>,
+ model_action : &ObservableAction,
+ new_interaction : &Interaction,
+ new_exe_ctx : &ExecutionContext,
+ remaining_multi_trace : &Option<AnalysableMultiTrace>) {
+ // *** Parent Interaction Node
+ let parent_interaction_node_name = format!("i{:}", parent_state_id);
+ // *** Firing Node
+ let current_node_name = format!("i{:}", new_state_id);
+ let firing_node_name = format!("f{:}", new_state_id);
+ {
+ let firing_node_path : String = format!("./temp/{:}_{}.png", self.log_name ,firing_node_name);
+ match trace_action {
+ None => {
+ draw_firing_on_model_action(&firing_node_path, action_position, model_action, gen_ctx, new_exe_ctx);
+ },
+ Some( got_trace_action ) => {
+ draw_firing_on_trace_against_model_action(&firing_node_path, action_position, got_trace_action, model_action, gen_ctx, new_exe_ctx);
+ }
+ }
+ // ***
+ let mut firing_gv_node_options : GraphvizNodeStyle = Vec::new();
+ firing_gv_node_options.push( GraphvizNodeStyleItem::Image( firing_node_path ) );
+ firing_gv_node_options.push(GraphvizNodeStyleItem::Label( "".to_string() ));
+ firing_gv_node_options.push( GraphvizNodeStyleItem::Shape(GvNodeShape::Rectangle) );
+ let firing_gv_node = GraphVizNode{id : firing_node_name.clone(), style : firing_gv_node_options};
+ self.file.write( firing_gv_node.to_dot_string().as_bytes() );
+ self.file.write("\n".as_bytes() );
+ }
+ // *** Transition To Firing
+ {
+ let mut tran_gv_options : GraphvizEdgeStyle = Vec::new();
+ tran_gv_options.push( GraphvizEdgeStyleItem::Head( GvArrowHeadStyle::Vee(GvArrowHeadSide::Both) ) );
+ let gv_edge = GraphVizEdge{origin_id : parent_interaction_node_name, target_id : firing_node_name.clone(), style : tran_gv_options};
+ self.file.write( gv_edge.to_dot_string().as_bytes() );
+ self.file.write("\n".as_bytes() );
+ }
+ // *** Resulting Interaction Node
+ {
+ let gv_path : String = format!("./temp/{:}_{}.png", self.log_name ,current_node_name);
+ draw_interaction(&gv_path, new_interaction, gen_ctx, new_exe_ctx, remaining_multi_trace);
+ // ***
+ let mut node_gv_options : GraphvizNodeStyle = Vec::new();
+ node_gv_options.push( GraphvizNodeStyleItem::Image( gv_path ) );
+ node_gv_options.push(GraphvizNodeStyleItem::Label( "".to_string() ));
+ node_gv_options.push( GraphvizNodeStyleItem::Shape(GvNodeShape::Rectangle) );
+ let gv_node = GraphVizNode{id : current_node_name.clone(), style : node_gv_options};
+ self.file.write( gv_node.to_dot_string().as_bytes() );
+ self.file.write("\n".as_bytes() );
+ }
+ // *** Transition To Interaction Node
+ {
+ let mut tran_gv_options : GraphvizEdgeStyle = Vec::new();
+ tran_gv_options.push( GraphvizEdgeStyleItem::Head( GvArrowHeadStyle::Vee(GvArrowHeadSide::Both) ) );
+ let gv_edge = GraphVizEdge{origin_id : firing_node_name, target_id : current_node_name, style : tran_gv_options};
+ self.file.write( gv_edge.to_dot_string().as_bytes() );
+ self.file.write("\n".as_bytes() );
+ }
+ }
+
+ fn log_filtered(&mut self,
+ gen_ctx : &GeneralContext,
+ exe_ctx:&ExecutionContext,
+ parent_state_id : u32,
+ new_state_id : u32,
+ action_position : &Position,
+ action : &ObservableAction,
+ elim_kind : &FilterEliminationKind) {
+ // *** Parent Interaction Node
+ let parent_interaction_node_name = format!("i{:}", parent_state_id);
+ // *** Firing Node
+ let elim_node_name = format!("e{:}", new_state_id);
+ let firing_node_name = format!("f{:}", new_state_id);
+ {
+ let firing_node_path : String = format!("./temp/{:}_{}.png", self.log_name ,firing_node_name);
+ draw_firing_on_model_action(&firing_node_path, action_position, action, gen_ctx, exe_ctx);
+ // ***
+ let mut firing_gv_node_options : GraphvizNodeStyle = Vec::new();
+ firing_gv_node_options.push( GraphvizNodeStyleItem::Image( firing_node_path ) );
+ firing_gv_node_options.push(GraphvizNodeStyleItem::Label( "".to_string() ));
+ firing_gv_node_options.push( GraphvizNodeStyleItem::Shape(GvNodeShape::Rectangle) );
+ let firing_gv_node = GraphVizNode{id : firing_node_name.clone(), style : firing_gv_node_options};
+ self.file.write( firing_gv_node.to_dot_string().as_bytes() );
+ self.file.write("\n".as_bytes() );
+ }
+ // *** Transition To Firing
+ {
+ let mut tran_gv_options : GraphvizEdgeStyle = Vec::new();
+ tran_gv_options.push( GraphvizEdgeStyleItem::Head( GvArrowHeadStyle::Vee(GvArrowHeadSide::Both) ) );
+ let gv_edge = GraphVizEdge{origin_id : parent_interaction_node_name, target_id : firing_node_name.clone(), style : tran_gv_options};
+ self.file.write( gv_edge.to_dot_string().as_bytes() );
+ self.file.write("\n".as_bytes() );
+ }
+ // *** Filtered Node
+ {
+ let mut node_gv_options : GraphvizNodeStyle = Vec::new();
+ // *****
+ node_gv_options.push( GraphvizNodeStyleItem::Label( elim_kind.to_string() ) );
+ // *****
+ node_gv_options.push( GraphvizNodeStyleItem::Color( GraphvizColor::burlywood4 ) );
+ node_gv_options.push( GraphvizNodeStyleItem::FontColor( GraphvizColor::beige ) );
+ node_gv_options.push( GraphvizNodeStyleItem::FontSize( 16 ) );
+ node_gv_options.push( GraphvizNodeStyleItem::FontName( "times-bold".to_string() ) );
+ node_gv_options.push( GraphvizNodeStyleItem::Shape(GvNodeShape::Pentagon) );
+ node_gv_options.push( GraphvizNodeStyleItem::Style(vec![GvNodeStyleKind::Filled]) );
+
+ let gv_node = GraphVizNode{id : elim_node_name.clone(), style : node_gv_options};
+ self.file.write( gv_node.to_dot_string().as_bytes() );
+ self.file.write("\n".as_bytes() );
+ }
+ // *** Transition To Filtered Node
+ {
+ let mut tran_gv_options : GraphvizEdgeStyle = Vec::new();
+ tran_gv_options.push( GraphvizEdgeStyleItem::Head( GvArrowHeadStyle::Vee(GvArrowHeadSide::Both) ) );
+ tran_gv_options.push( GraphvizEdgeStyleItem::Color( GraphvizColor::burlywood4 ) );
+ let gv_edge = GraphVizEdge{origin_id : firing_node_name, target_id : elim_node_name, style : tran_gv_options};
+ self.file.write( gv_edge.to_dot_string().as_bytes() );
+ self.file.write("\n".as_bytes() );
+ }
+ }
+
+ fn log_unsat(&mut self,
+ gen_ctx : &GeneralContext,
+ exe_ctx:&ExecutionContext,
+ parent_state_id : u32,
+ new_state_id : u32,
+ action_position : &Position,
+ trace_action : Option<&TraceAction>,
+ model_action : &ObservableAction) {
+ // *** Parent Interaction Node
+ let parent_interaction_node_name = format!("i{:}", parent_state_id);
+ // *** Firing Node
+ let unsat_node_name = format!("u{:}", new_state_id);
+ let firing_node_name = format!("f{:}", new_state_id);
+ {
+ let firing_node_path : String = format!("./temp/{:}_{}.png", self.log_name ,firing_node_name);
+ match trace_action {
+ None => {
+ draw_firing_on_model_action(&firing_node_path, action_position, model_action, gen_ctx, exe_ctx);
+ },
+ Some( got_trace_action ) => {
+ draw_firing_on_trace_against_model_action(&firing_node_path, action_position, got_trace_action, model_action, gen_ctx, exe_ctx);
+ }
+ }
+ // ***
+ let mut firing_gv_node_options : GraphvizNodeStyle = Vec::new();
+ firing_gv_node_options.push( GraphvizNodeStyleItem::Image( firing_node_path ) );
+ firing_gv_node_options.push(GraphvizNodeStyleItem::Label( "".to_string() ));
+ firing_gv_node_options.push( GraphvizNodeStyleItem::Shape(GvNodeShape::Rectangle) );
+ let firing_gv_node = GraphVizNode{id : firing_node_name.clone(), style : firing_gv_node_options};
+ self.file.write( firing_gv_node.to_dot_string().as_bytes() );
+ self.file.write("\n".as_bytes() );
+ }
+ // *** Transition To Firing
+ {
+ let mut tran_gv_options : GraphvizEdgeStyle = Vec::new();
+ tran_gv_options.push( GraphvizEdgeStyleItem::Head( GvArrowHeadStyle::Vee(GvArrowHeadSide::Both) ) );
+ let gv_edge = GraphVizEdge{origin_id : parent_interaction_node_name, target_id : firing_node_name.clone(), style : tran_gv_options};
+ self.file.write( gv_edge.to_dot_string().as_bytes() );
+ self.file.write("\n".as_bytes() );
+ }
+ // *** UNSAT Node
+ {
+ let mut node_gv_options : GraphvizNodeStyle = Vec::new();
+ // *****
+ node_gv_options.push( GraphvizNodeStyleItem::Label( "UNSAT".to_string() ) );
+ // *****
+ node_gv_options.push( GraphvizNodeStyleItem::Color( GraphvizColor::red4 ) );
+ node_gv_options.push( GraphvizNodeStyleItem::FontColor( GraphvizColor::beige ) );
+ node_gv_options.push( GraphvizNodeStyleItem::FontSize( 16 ) );
+ node_gv_options.push( GraphvizNodeStyleItem::FontName( "times-bold".to_string() ) );
+ node_gv_options.push( GraphvizNodeStyleItem::Shape(GvNodeShape::Septagon) );
+ node_gv_options.push( GraphvizNodeStyleItem::Style(vec![GvNodeStyleKind::Filled]) );
+
+ let gv_node = GraphVizNode{id : unsat_node_name.clone(), style : node_gv_options};
+ self.file.write( gv_node.to_dot_string().as_bytes() );
+ self.file.write("\n".as_bytes() );
+ }
+ // *** Transition To UNSAT Node
+ {
+ let mut tran_gv_options : GraphvizEdgeStyle = Vec::new();
+ tran_gv_options.push( GraphvizEdgeStyleItem::Head( GvArrowHeadStyle::Vee(GvArrowHeadSide::Both) ) );
+ tran_gv_options.push( GraphvizEdgeStyleItem::Color( GraphvizColor::red4 ) );
+ let gv_edge = GraphVizEdge{origin_id : firing_node_name, target_id : unsat_node_name, style : tran_gv_options};
+ self.file.write( gv_edge.to_dot_string().as_bytes() );
+ self.file.write("\n".as_bytes() );
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/rendering/process/mod.rs b/src/rendering/process/mod.rs
new file mode 100644
index 0000000..99eea6d
--- /dev/null
+++ b/src/rendering/process/mod.rs
@@ -0,0 +1,17 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+pub mod graphic_logger;
+pub mod verdict;
\ No newline at end of file
diff --git a/src/rendering/process/verdict.rs b/src/rendering/process/verdict.rs
new file mode 100644
index 0000000..434e04d
--- /dev/null
+++ b/src/rendering/process/verdict.rs
@@ -0,0 +1,43 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+use crate::process::verdicts::CoverageVerdict;
+
+use crate::rendering::graphviz::common::GraphvizColor;
+
+
+impl CoverageVerdict {
+ pub fn get_verdict_color(&self) -> GraphvizColor {
+ match self {
+ CoverageVerdict::Cov => {
+ return GraphvizColor::blue3;
+ },
+ CoverageVerdict::TooShort => {
+ return GraphvizColor::cyan3;
+ },
+ CoverageVerdict::LackObs => {
+ return GraphvizColor::orangered3;
+ },
+ CoverageVerdict::Out => {
+ return GraphvizColor::red3;
+ }
+ }
+ }
+}
+
+
+
+
+
diff --git a/src/rendering/sd_drawing_conf.rs b/src/rendering/sd_drawing_conf.rs
new file mode 100644
index 0000000..e6b4730
--- /dev/null
+++ b/src/rendering/sd_drawing_conf.rs
@@ -0,0 +1,53 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub const HIBOU_GRAPHIC_FONT: &'static [u8] = include_bytes!("DejaVuSansMono.ttf");
+
+// **********
+pub const BASE_HORIZONTAL_SIZE : f32 = 50.0; // 100.0
+pub const BASE_VERTICAL_SIZE : f32 = 5.5; //11.0; // 12.5
+pub const BASE_MARGIN : f32 = BASE_VERTICAL_SIZE; // 10.0
+pub const BASE_FRAGMENT_PADDING : f32 = 5.0;
+pub const BASE_FRAGMENT_TITLE_MARGIN : f32 = 1.0;
+// **********
+//pub const BASE_ACTOR_WIDTH : f32 = BASE_HORIZONTAL_SIZE/3.0;
+//pub const BASE_ACTOR_HEIGHT : f32 = 10.0;
+// **********
+pub const BASE_THICKNESS : f32 = 1.0;
+pub const BASE_FONT_HEIGHT : f32 = 12.4;
+pub const BASE_EVAL_X_PADDING : f32 = BASE_HORIZONTAL_SIZE/3.5;
+pub const BASE_EVAL_HEIGHT : f32 = BASE_VERTICAL_SIZE/3.0;
+pub const BASE_ARROW_HEAD_LENGTH : f32 = 5.0;
+pub const BASE_FRONTIER_CIRCLE_RADIUS : f32 = 5.0;
+// **********
+const SCALE_FACTOR : f32 = 2.0;
+// **********
+pub const MARGIN : f32 = BASE_MARGIN*SCALE_FACTOR;
+pub const HORIZONTAL_SIZE : f32 = BASE_HORIZONTAL_SIZE*SCALE_FACTOR;
+pub const VERTICAL_SIZE : f32 = BASE_VERTICAL_SIZE*SCALE_FACTOR;
+pub const FRAGMENT_PADDING : f32 = BASE_FRAGMENT_PADDING*SCALE_FACTOR;
+pub const FRAGMENT_TITLE_MARGIN : f32 = BASE_FRAGMENT_TITLE_MARGIN*SCALE_FACTOR;
+// **********
+//pub const ACTOR_WIDTH : f32 = BASE_ACTOR_WIDTH*SCALE_FACTOR;
+//pub const ACTOR_HEIGHT : f32 = BASE_ACTOR_HEIGHT*SCALE_FACTOR;
+// **********
+pub const THICKNESS : f32 = BASE_THICKNESS*SCALE_FACTOR;
+pub const FONT_HEIGHT : f32 = BASE_FONT_HEIGHT*SCALE_FACTOR;
+pub const FONT_X_PROPORTION : f32 = 1.0;
+pub const FONT_WIDTH : f32 = FONT_HEIGHT*FONT_X_PROPORTION;
+pub const EVAL_X_PADDING : f32 = BASE_EVAL_X_PADDING*SCALE_FACTOR;
+pub const EVAL_HEIGHT : f32 = BASE_EVAL_HEIGHT*SCALE_FACTOR;
+pub const ARROW_HEAD_LENGTH : f32 = BASE_ARROW_HEAD_LENGTH*SCALE_FACTOR;
+pub const FRONTIER_CIRCLE_RADIUS : f32 = BASE_FRONTIER_CIRCLE_RADIUS*SCALE_FACTOR;
+// **********
\ No newline at end of file
diff --git a/src/rendering/textual/colored/amble.rs b/src/rendering/textual/colored/amble.rs
new file mode 100644
index 0000000..e99572d
--- /dev/null
+++ b/src/rendering/textual/colored/amble.rs
@@ -0,0 +1,60 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use image::Rgb;
+
+use crate::core::syntax::action::*;
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::rendering::textual::convention::*;
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::hibou_color_palette::*;
+
+
+pub fn diagram_revr_amble(amble : &Vec<ActionAmbleItem>,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext) -> Vec<Vec<TextToPrint>> {
+ let mut to_print_items : Vec<Vec<TextToPrint>> = Vec::new();
+ for am_item in amble {
+ match am_item {
+ ActionAmbleItem::Guard( td_bool ) => {
+ to_print_items.push( td_bool.to_colored_text(gen_ctx,exe_ctx) );
+ },
+ ActionAmbleItem::Reset( vr_id ) => {
+ let mut inner : Vec<TextToPrint> = Vec::new();
+ inner.push( TextToPrint{text:"reset ".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ let vr_name = exe_ctx.get_vr_name(gen_ctx, *vr_id).unwrap();
+ inner.push( TextToPrint{text:vr_name,color:Rgb(HC_Variable)} );
+ to_print_items.push( inner );
+ },
+ ActionAmbleItem::Assignment( vr_id, valueornewfresh) => {
+ let mut inner : Vec<TextToPrint> = Vec::new();
+ let vr_name = exe_ctx.get_vr_name(gen_ctx, *vr_id).unwrap();
+ inner.push( TextToPrint{text:vr_name,color:Rgb(HC_Variable)} );
+ inner.push( TextToPrint{text:":=".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ match valueornewfresh {
+ ValueOrNewFresh::Value( td_generic ) => {
+ inner.append( &mut td_generic.to_colored_text(gen_ctx,exe_ctx));
+ },
+ ValueOrNewFresh::NewFresh => {
+ inner.push( TextToPrint{text:SYNTAX_NEWFRESH.to_string(),color:Rgb(HC_NewFresh)} );
+ }
+ }
+ to_print_items.push( inner );
+ }
+ }
+ }
+ return to_print_items;
+}
\ No newline at end of file
diff --git a/src/rendering/textual/colored/colored_text.rs b/src/rendering/textual/colored/colored_text.rs
new file mode 100644
index 0000000..49db375
--- /dev/null
+++ b/src/rendering/textual/colored/colored_text.rs
@@ -0,0 +1,68 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use image::Rgb;
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub struct TextToPrint {
+ pub text : String,
+ pub color : Rgb<u8>
+}
+
+impl TextToPrint {
+ pub fn flatten(to_print : &Vec<TextToPrint>) -> String {
+ let mut flattened : String = String::new();
+ for ttp in to_print {
+ flattened.push_str(&ttp.text);
+ }
+ return flattened;
+ }
+
+ pub fn char_count(to_print : &Vec<TextToPrint>) -> usize {
+ let mut count : usize = 0;
+ for ttp in to_print {
+ count = count + ttp.text.chars().count();
+ }
+ return count;
+ }
+
+ pub fn contains_sub_str(to_print : &Vec<TextToPrint>, sub_str : &str) -> bool {
+ for ttp in to_print {
+ if ttp.text.contains(sub_str) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /*
+ pub fn contains_one_of_sub_strs(to_print : &Vec<TextToPrint>, sub_strs : Vec<&str>) -> bool {
+ for ttp in to_print {
+ for sub_str in &sub_strs {
+ if ttp.text.contains(sub_str) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }*/
+}
+
+pub trait ColoredTextable {
+
+ fn to_colored_text(&self, gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext) -> Vec<TextToPrint>;
+
+}
diff --git a/src/rendering/textual/colored/data/bool.rs b/src/rendering/textual/colored/data/bool.rs
new file mode 100644
index 0000000..80a3482
--- /dev/null
+++ b/src/rendering/textual/colored/data/bool.rs
@@ -0,0 +1,101 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use image::Rgb;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::data::builtin::bool::*;
+
+use crate::rendering::hibou_color_palette::*;
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::textual::convention::*;
+
+impl ColoredTextable for TD_Bool {
+ fn to_colored_text(&self, gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext) -> Vec<TextToPrint> {
+ match self {
+ TD_Bool::TRUE => {
+ return vec![ TextToPrint{text:SYNTAX_LOGIC_TRUE.to_string(),color:Rgb(HC_Concrete_Value)} ];
+ },
+ TD_Bool::FALSE => {
+ return vec![ TextToPrint{text:SYNTAX_LOGIC_FALSE.to_string(),color:Rgb(HC_Concrete_Value)} ];
+ },
+ TD_Bool::AND( bool_vec ) => {
+ let mut texts : Vec<TextToPrint> = Vec::new();
+ texts.push( TextToPrint{text:"(".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ for idx in 0..bool_vec.len() {
+ let td_bool = bool_vec.get(idx).unwrap();
+ texts.append(&mut td_bool.to_colored_text(gen_ctx,exe_ctx));
+ if idx < bool_vec.len()-1 {
+ texts.push( TextToPrint{text:SYNTAX_LOGIC_AND.to_string(),color:Rgb(HC_Grammar_Symbol)});
+ }
+ }
+ texts.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ return texts;
+ },
+ TD_Bool::OR( bool_vec ) => {
+ let mut texts : Vec<TextToPrint> = Vec::new();
+ texts.push( TextToPrint{text:"(".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ for idx in 0..bool_vec.len() {
+ let td_bool = bool_vec.get(idx).unwrap();
+ texts.append(&mut td_bool.to_colored_text(gen_ctx,exe_ctx));
+ if idx < bool_vec.len()-1 {
+ texts.push( TextToPrint{text:SYNTAX_LOGIC_OR.to_string(),color:Rgb(HC_Grammar_Symbol)});
+ }
+ }
+ texts.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ return texts;
+ },
+ TD_Bool::NOT( td_bool ) => {
+ let mut texts : Vec<TextToPrint> = Vec::new();
+ texts.push( TextToPrint{text:"(".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ texts.push( TextToPrint{text:SYNTAX_LOGIC_NOT.to_string(),color:Rgb(HC_Grammar_Symbol)});
+ texts.append(&mut td_bool.to_colored_text(gen_ctx,exe_ctx));
+ texts.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ return texts;
+ },
+ TD_Bool::COMPARE( kind, td_generic1, td_generic2 ) => {
+ let mut texts : Vec<TextToPrint> = Vec::new();
+ texts.push( TextToPrint{text:"(".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ texts.append(&mut td_generic1.to_colored_text(gen_ctx,exe_ctx));
+ match kind {
+ Bool_Compare::Different => {
+ texts.push( TextToPrint{text:SYNTAX_COMPARE_Diff.to_string(),color:Rgb(HC_Grammar_Symbol)});
+ },
+ Bool_Compare::Equal => {
+ texts.push( TextToPrint{text:SYNTAX_COMPARE_Eq.to_string(),color:Rgb(HC_Grammar_Symbol)});
+ },
+ Bool_Compare::Greater => {
+ texts.push( TextToPrint{text:SYNTAX_COMPARE_Gr.to_string(),color:Rgb(HC_Grammar_Symbol)});
+ },
+ Bool_Compare::GreaterOrEqual => {
+ texts.push( TextToPrint{text:SYNTAX_COMPARE_GrEq.to_string(),color:Rgb(HC_Grammar_Symbol)});
+ },
+ Bool_Compare::Lower => {
+ texts.push( TextToPrint{text:SYNTAX_COMPARE_Lr.to_string(),color:Rgb(HC_Grammar_Symbol)});
+ },
+ Bool_Compare::LowerOrEqual => {
+ texts.push( TextToPrint{text:SYNTAX_COMPARE_LrEq.to_string(),color:Rgb(HC_Grammar_Symbol)});
+ }
+ }
+ texts.append(&mut td_generic2.to_colored_text(gen_ctx,exe_ctx));
+ texts.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ return texts;
+ },
+ TD_Bool::Reference( var_ref ) => {
+ return var_ref.to_colored_text(gen_ctx,exe_ctx);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/rendering/textual/colored/data/float.rs b/src/rendering/textual/colored/data/float.rs
new file mode 100644
index 0000000..234f23b
--- /dev/null
+++ b/src/rendering/textual/colored/data/float.rs
@@ -0,0 +1,89 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use image::Rgb;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::data::builtin::float::*;
+use crate::core::syntax::data::builtin::number::*;
+
+use crate::rendering::hibou_color_palette::*;
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::textual::convention::*;
+
+impl ColoredTextable for TD_Float {
+ fn to_colored_text(&self, gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext) -> Vec<TextToPrint> {
+ match self {
+ TD_Float::Value( fval ) => {
+ return vec![ TextToPrint{text:format!("{:e}", fval),color:Rgb(HC_Concrete_Value)} ];
+ },
+ TD_Float::Minus( td_num ) => {
+ let mut texts : Vec<TextToPrint> = Vec::new();
+ texts.push( TextToPrint{text:"(".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ texts.push( TextToPrint{text:"-".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ texts.append( &mut td_num.to_colored_text(gen_ctx,exe_ctx));
+ texts.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ return texts;
+ },
+ TD_Float::Factor( factors ) => {
+ let mut texts : Vec<TextToPrint> = Vec::new();
+ texts.push( TextToPrint{text:"(".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ let mut count : usize = 0;
+ for (sign,td_num) in factors {
+ if count > 0 {
+ texts.push( TextToPrint{text:"*".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ }
+ count = count +1;
+ match sign {
+ ARITH_FACTOR_SIGN::Div => {
+ texts.push( TextToPrint{text:"(1.0/".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ texts.append( &mut td_num.to_colored_text(gen_ctx,exe_ctx));
+ texts.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ },
+ ARITH_FACTOR_SIGN::Mult => {
+ texts.append( &mut td_num.to_colored_text(gen_ctx,exe_ctx));
+ }
+ }
+ }
+ texts.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ return texts;
+ },
+ TD_Float::Add( adds ) => {
+ let mut texts : Vec<TextToPrint> = Vec::new();
+ texts.push( TextToPrint{text:"(".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ let mut count : usize = 0;
+ for (sign,td_num) in adds {
+ match sign {
+ ARITH_ADD_SIGN::Plus => {
+ if count > 0 {
+ texts.push( TextToPrint{text:"+".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ }
+ },
+ ARITH_ADD_SIGN::Minus => {
+ texts.push( TextToPrint{text:"-".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ }
+ }
+ count = count +1;
+ texts.append( &mut td_num.to_colored_text(gen_ctx,exe_ctx));
+ }
+ texts.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ return texts;
+ },
+ TD_Float::Reference( var_ref ) => {
+ return var_ref.to_colored_text(gen_ctx,exe_ctx);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/rendering/textual/colored/data/generic.rs b/src/rendering/textual/colored/data/generic.rs
new file mode 100644
index 0000000..6b26c9c
--- /dev/null
+++ b/src/rendering/textual/colored/data/generic.rs
@@ -0,0 +1,44 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::data::generic::TD_Generic;
+
+
+use crate::rendering::textual::colored::colored_text::*;
+
+
+impl ColoredTextable for TD_Generic {
+ fn to_colored_text(&self, gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext) -> Vec<TextToPrint> {
+ match self {
+ TD_Generic::Bool( td_bool ) => {
+ return td_bool.to_colored_text(gen_ctx,exe_ctx);
+ },
+ TD_Generic::Integer( td_int ) => {
+ return td_int.to_colored_text(gen_ctx,exe_ctx);
+ },
+ TD_Generic::Float( td_float ) => {
+ return td_float.to_colored_text(gen_ctx,exe_ctx);
+ },
+ TD_Generic::String( td_str ) => {
+ return td_str.to_colored_text(gen_ctx,exe_ctx);
+ }/*,
+ TD_Generic::Reference( var_ref ) => {
+ return var_ref.to_colored_text(gen_ctx,exe_ctx);
+ }*/
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/rendering/textual/colored/data/integer.rs b/src/rendering/textual/colored/data/integer.rs
new file mode 100644
index 0000000..a190463
--- /dev/null
+++ b/src/rendering/textual/colored/data/integer.rs
@@ -0,0 +1,89 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use image::Rgb;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::data::builtin::integer::*;
+use crate::core::syntax::data::builtin::number::*;
+
+use crate::rendering::hibou_color_palette::*;
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::textual::convention::*;
+
+impl ColoredTextable for TD_Integer {
+ fn to_colored_text(&self, gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext) -> Vec<TextToPrint> {
+ match self {
+ TD_Integer::Value( ival ) => {
+ return vec![ TextToPrint{text:ival.to_string(),color:Rgb(HC_Concrete_Value)} ];
+ },
+ TD_Integer::Minus( td_num ) => {
+ let mut texts : Vec<TextToPrint> = Vec::new();
+ texts.push( TextToPrint{text:"(".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ texts.push( TextToPrint{text:"-".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ texts.append( &mut td_num.to_colored_text(gen_ctx,exe_ctx));
+ texts.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ return texts;
+ },
+ TD_Integer::Factor( factors ) => {
+ let mut texts : Vec<TextToPrint> = Vec::new();
+ texts.push( TextToPrint{text:"(".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ let mut count : usize = 0;
+ for (sign,td_num) in factors {
+ if count > 0 {
+ texts.push( TextToPrint{text:"*".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ }
+ count = count +1;
+ match sign {
+ ARITH_FACTOR_SIGN::Div => {
+ texts.push( TextToPrint{text:"(1/".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ texts.append( &mut td_num.to_colored_text(gen_ctx,exe_ctx));
+ texts.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ },
+ ARITH_FACTOR_SIGN::Mult => {
+ texts.append( &mut td_num.to_colored_text(gen_ctx,exe_ctx));
+ }
+ }
+ }
+ texts.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ return texts;
+ },
+ TD_Integer::Add( adds ) => {
+ let mut texts : Vec<TextToPrint> = Vec::new();
+ texts.push( TextToPrint{text:"(".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ let mut count : usize = 0;
+ for (sign,td_num) in adds {
+ match sign {
+ ARITH_ADD_SIGN::Plus => {
+ if count > 0 {
+ texts.push( TextToPrint{text:"+".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ }
+ },
+ ARITH_ADD_SIGN::Minus => {
+ texts.push( TextToPrint{text:"-".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ }
+ }
+ count = count +1;
+ texts.append( &mut td_num.to_colored_text(gen_ctx,exe_ctx));
+ }
+ texts.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ return texts;
+ },
+ TD_Integer::Reference( var_ref ) => {
+ return var_ref.to_colored_text(gen_ctx,exe_ctx);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/rendering/textual/colored/data/mod.rs b/src/rendering/textual/colored/data/mod.rs
new file mode 100644
index 0000000..f0a664f
--- /dev/null
+++ b/src/rendering/textual/colored/data/mod.rs
@@ -0,0 +1,21 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod generic;
+pub mod bool;
+pub mod integer;
+pub mod float;
+pub mod string;
+pub mod var_ref;
+pub mod value_or_newfresh;
\ No newline at end of file
diff --git a/src/rendering/textual/colored/data/string.rs b/src/rendering/textual/colored/data/string.rs
new file mode 100644
index 0000000..ad645fd
--- /dev/null
+++ b/src/rendering/textual/colored/data/string.rs
@@ -0,0 +1,40 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use image::Rgb;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::data::builtin::string::TD_String;
+
+use crate::rendering::hibou_color_palette::*;
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::textual::convention::*;
+
+impl ColoredTextable for TD_String {
+ fn to_colored_text(&self, gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext) -> Vec<TextToPrint> {
+ match self {
+ TD_String::Value( str_val ) => {
+ let mut texts : Vec<TextToPrint> = Vec::new();
+ texts.push( TextToPrint{text:"\"".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ texts.push( TextToPrint{text:str_val.to_string(),color:Rgb(HC_Concrete_Value)} );
+ texts.push( TextToPrint{text:"\"".to_string(),color:Rgb(HC_Grammar_Symbol)});
+ return texts;
+ },
+ TD_String::Reference( var_ref ) => {
+ return var_ref.to_colored_text(gen_ctx,exe_ctx);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/rendering/textual/colored/data/value_or_newfresh.rs b/src/rendering/textual/colored/data/value_or_newfresh.rs
new file mode 100644
index 0000000..3ee8328
--- /dev/null
+++ b/src/rendering/textual/colored/data/value_or_newfresh.rs
@@ -0,0 +1,36 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use image::Rgb;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::action::ValueOrNewFresh;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::rendering::textual::convention::*;
+use crate::rendering::hibou_color_palette::*;
+use crate::rendering::textual::colored::colored_text::*;
+
+impl ColoredTextable for ValueOrNewFresh {
+ fn to_colored_text(&self, gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext) -> Vec<TextToPrint> {
+ match self {
+ ValueOrNewFresh::NewFresh => {
+ return vec![ TextToPrint{text:SYNTAX_NEWFRESH.to_string(),color:Rgb(HC_NewFresh)} ];
+ },
+ ValueOrNewFresh::Value( td_generic ) => {
+ return td_generic.to_colored_text(gen_ctx,exe_ctx);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/rendering/textual/colored/data/var_ref.rs b/src/rendering/textual/colored/data/var_ref.rs
new file mode 100644
index 0000000..2634d9a
--- /dev/null
+++ b/src/rendering/textual/colored/data/var_ref.rs
@@ -0,0 +1,42 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use image::Rgb;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::data::var_ref::VariableReference;
+
+use crate::rendering::hibou_color_palette::*;
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::textual::convention::*;
+
+impl ColoredTextable for VariableReference {
+ fn to_colored_text(&self, gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext) -> Vec<TextToPrint> {
+ match self {
+ VariableReference::MSG_PARAMETER( ms_id, pr_id ) => {
+ let text = format!("${:}",pr_id.to_string());
+ return vec![ TextToPrint{text:text,color:Rgb(HC_MessageParameter)} ];
+ },
+ VariableReference::VARIABLE( vr_id ) => {
+ let vr_name = exe_ctx.get_vr_name(gen_ctx, *vr_id).unwrap();
+ return vec![ TextToPrint{text:vr_name,color:Rgb(HC_Variable)} ];
+ },
+ VariableReference::SYMBOL( symb_id ) => {
+ let text = format!("{:}{:}",SYNTAX_NEWFRESH,symb_id.to_string());
+ return vec![ TextToPrint{text:text,color:Rgb(HC_Symbol)} ];
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/rendering/textual/colored/message.rs b/src/rendering/textual/colored/message.rs
new file mode 100644
index 0000000..70c75fe
--- /dev/null
+++ b/src/rendering/textual/colored/message.rs
@@ -0,0 +1,97 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use image::Rgb;
+
+use crate::core::syntax::action::*;
+use crate::core::context::general::GeneralContext;
+
+use crate::core::context::execution::ExecutionContext;
+
+use crate::rendering::textual::convention::*;
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::hibou_color_palette::*;
+use crate::core::syntax::data::generic::TD_Generic;
+
+pub fn diagram_repr_message(ms_id : usize,
+ params : &Vec<ValueOrNewFresh>,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext) -> Vec<TextToPrint> {
+ let mut to_print: Vec<TextToPrint> = Vec::new();
+ // ***
+ match gen_ctx.get_ms_name(ms_id) {
+ Err(_) => {
+ println!("WARNING action message name not found for display");
+ panic!();
+ },
+ Ok( ms_name ) => {
+ to_print.push( TextToPrint{text:ms_name,color:Rgb(HC_Message)} );
+ }
+ }
+ // ***
+ let prm_num = params.len();
+ if prm_num > 0 {
+ to_print.push( TextToPrint{text:"(".to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ let mut current_prm : usize = 0;
+ for value_or_new_fresh in params {
+ match value_or_new_fresh {
+ ValueOrNewFresh::Value( td_generic ) => {
+ to_print.append( &mut td_generic.to_colored_text(gen_ctx,exe_ctx));
+ },
+ ValueOrNewFresh::NewFresh => {
+ to_print.push( TextToPrint{text:SYNTAX_NEWFRESH.to_string(),color:Rgb(HC_NewFresh)} );
+ }
+ }
+ current_prm = current_prm +1;
+ if current_prm < prm_num {
+ to_print.push( TextToPrint{text:",".to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ }
+ }
+ to_print.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ }
+ return to_print;
+}
+
+
+pub fn diagram_repr_raw_message(ms_id : usize,
+ arguments : &Vec<TD_Generic>,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext) -> Vec<TextToPrint> {
+ let mut to_print: Vec<TextToPrint> = Vec::new();
+ // ***
+ match gen_ctx.get_ms_name(ms_id) {
+ Err(_) => {
+ println!("WARNING action message name not found for display");
+ panic!();
+ },
+ Ok( ms_name ) => {
+ to_print.push( TextToPrint{text:ms_name,color:Rgb(HC_Message)} );
+ }
+ }
+ // ***
+ let prm_num = arguments.len();
+ if prm_num > 0 {
+ to_print.push( TextToPrint{text:"(".to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ let mut current_prm : usize = 0;
+ for td_generic in arguments {
+ to_print.append( &mut td_generic.to_colored_text(gen_ctx,exe_ctx));
+ current_prm = current_prm +1;
+ if current_prm < prm_num {
+ to_print.push( TextToPrint{text:",".to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ }
+ }
+ to_print.push( TextToPrint{text:")".to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ }
+ return to_print;
+}
\ No newline at end of file
diff --git a/src/rendering/textual/colored/mod.rs b/src/rendering/textual/colored/mod.rs
new file mode 100644
index 0000000..529b3a4
--- /dev/null
+++ b/src/rendering/textual/colored/mod.rs
@@ -0,0 +1,19 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod colored_text;
+pub mod data;
+pub mod amble;
+pub mod message;
+pub mod short_action;
diff --git a/src/rendering/textual/colored/short_action.rs b/src/rendering/textual/colored/short_action.rs
new file mode 100644
index 0000000..d9c5c34
--- /dev/null
+++ b/src/rendering/textual/colored/short_action.rs
@@ -0,0 +1,89 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use image::Rgb;
+
+use crate::core::syntax::action::*;
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::rendering::textual::convention::*;
+use crate::rendering::textual::colored::colored_text::*;
+use crate::rendering::hibou_color_palette::*;
+
+use crate::rendering::textual::colored::message::{diagram_repr_message,diagram_repr_raw_message};
+use crate::core::trace::{TraceAction,TraceActionKind};
+
+
+pub fn diagram_repr_atomic_trace_action(action : &TraceAction,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext) -> Vec<TextToPrint> {
+ let mut to_print : Vec<TextToPrint> = Vec::new();
+ // ***
+ match &action.delay {
+ None => {
+ // nothing
+ },
+ Some( delay_td_float ) => {
+ to_print.push( TextToPrint{text:"[".to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ to_print.append(&mut delay_td_float.to_colored_text(gen_ctx,&exe_ctx) );
+ to_print.push( TextToPrint{text:"].".to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ }
+ }
+ // ***
+ {
+ let lf_name: String = exe_ctx.get_lf_name(gen_ctx,action.lf_id).unwrap();
+ to_print.push( TextToPrint{text:lf_name,color:Rgb(HC_Lifeline)} );
+ }
+ // ***
+ match &action.act_kind {
+ &TraceActionKind::Reception => {
+ to_print.push( TextToPrint{text:SYNTAX_RECEPTION.to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ },
+ &TraceActionKind::Emission => {
+ to_print.push( TextToPrint{text:SYNTAX_EMISSION.to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ }
+ }
+ // ***
+ to_print.append( &mut diagram_repr_raw_message(action.ms_id, &action.arguments,gen_ctx,exe_ctx));
+ // ***
+ return to_print;
+}
+
+
+
+pub fn diagram_repr_atomic_model_action(action : &ObservableAction,
+ gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext) -> Vec<TextToPrint> {
+ let mut to_print : Vec<TextToPrint> = Vec::new();
+ // ***
+ {
+ let lf_name: String = exe_ctx.get_lf_name(gen_ctx,action.lf_act.lf_id).unwrap();
+ to_print.push( TextToPrint{text:lf_name,color:Rgb(HC_Lifeline)} );
+ }
+ // ***
+ match &action.act_kind {
+ &ObservableActionKind::Reception => {
+ to_print.push( TextToPrint{text:SYNTAX_RECEPTION.to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ },
+ &ObservableActionKind::Emission(_) => {
+ to_print.push( TextToPrint{text:SYNTAX_EMISSION.to_string(),color:Rgb(HC_Grammar_Symbol)} );
+ }
+ }
+ // ***
+ to_print.append( &mut diagram_repr_message(action.ms_id, &action.params,gen_ctx,exe_ctx));
+ // ***
+ return to_print;
+}
\ No newline at end of file
diff --git a/src/rendering/textual/convention.rs b/src/rendering/textual/convention.rs
new file mode 100644
index 0000000..e50cbf2
--- /dev/null
+++ b/src/rendering/textual/convention.rs
@@ -0,0 +1,62 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+
+
+pub static SYNTAX_STRICT: &'static str = "strict";
+pub static SYNTAX_SEQ: &'static str = "seq";
+pub static SYNTAX_PAR: &'static str = "par";
+pub static SYNTAX_ALT: &'static str = "alt";
+pub static SYNTAX_SCOPE: &'static str = "scope";
+pub static SYNTAX_LOOP: &'static str = "loop_";
+pub static SYNTAX_LOOP_STRICT: &'static str = "loop_strict";
+pub static SYNTAX_LOOP_SEQ: &'static str = "loop_seq";
+pub static SYNTAX_LOOP_PAR: &'static str = "loop_par";
+
+pub static SYNTAX_BREAK: &'static str = "break";
+pub static SYNTAX_CONTINUE: &'static str = "continue";
+
+pub static SYNTAX_EMISSION: &'static str = "!";
+pub static SYNTAX_RECEPTION: &'static str = "?";
+pub static SYNTAX_LOGGING: &'static str = ":";
+
+
+pub static SYNTAX_POROSITY: &'static str = "^";
+
+pub static SYNTAX_SCOPE_START: &'static str = "{";
+pub static SYNTAX_SCOPE_SEPARATOR: &'static str = ",";
+pub static SYNTAX_SCOPE_END: &'static str = "}";
+
+
+
+
+pub static SYNTAX_LOGIC_TRUE: &'static str = "⊤";
+pub static SYNTAX_LOGIC_FALSE: &'static str = "⊥";
+pub static SYNTAX_LOGIC_AND: &'static str = "∧";
+pub static SYNTAX_LOGIC_OR: &'static str = "∨";
+pub static SYNTAX_LOGIC_NOT: &'static str = "¬";
+
+pub static SYNTAX_COMPARE_Diff: &'static str = "≠";
+pub static SYNTAX_COMPARE_Eq: &'static str = "=";
+pub static SYNTAX_COMPARE_Gr: &'static str = ">";
+pub static SYNTAX_COMPARE_GrEq: &'static str = "≥";
+pub static SYNTAX_COMPARE_Lr: &'static str = "<";
+pub static SYNTAX_COMPARE_LrEq: &'static str = "≤";
+
+pub static SYNTAX_NEWFRESH: &'static str = "#"; //"※";
+
+
+
+
diff --git a/src/rendering/textual/mod.rs b/src/rendering/textual/mod.rs
new file mode 100644
index 0000000..cd56292
--- /dev/null
+++ b/src/rendering/textual/mod.rs
@@ -0,0 +1,23 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod convention;
+
+pub mod colored;
+
+pub mod monochrome;
+
+
+
+
diff --git a/src/rendering/textual/monochrome/mod.rs b/src/rendering/textual/monochrome/mod.rs
new file mode 100644
index 0000000..e13e500
--- /dev/null
+++ b/src/rendering/textual/monochrome/mod.rs
@@ -0,0 +1,17 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod position;
+//pub mod short_action;
+//pub mod trace;
\ No newline at end of file
diff --git a/src/rendering/textual/monochrome/position.rs b/src/rendering/textual/monochrome/position.rs
new file mode 100644
index 0000000..67ff60b
--- /dev/null
+++ b/src/rendering/textual/monochrome/position.rs
@@ -0,0 +1,39 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use crate::core::syntax::position::*;
+
+pub fn position_to_text(position : &Position) -> String {
+ match position {
+ Position::Left(ref in_self) => {
+ let mut my_string = SYNTAX_POSITION_LEFT.to_string();
+ let sub_pos = position_to_text( &(*in_self) );
+ if sub_pos != SYNTAX_POSITION_EPSILON.to_string() {
+ my_string.push_str( &sub_pos );
+ }
+ return my_string;
+ },
+ Position::Right(ref in_self) => {
+ let mut my_string = SYNTAX_POSITION_RIGHT.to_string();
+ let sub_pos = position_to_text( &(*in_self) );
+ if sub_pos != SYNTAX_POSITION_EPSILON.to_string() {
+ my_string.push_str( &sub_pos );
+ }
+ return my_string;
+ },
+ Position::Epsilon => {
+ return SYNTAX_POSITION_EPSILON.to_string();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/rendering/textual/monochrome/short_action.rs b/src/rendering/textual/monochrome/short_action.rs
new file mode 100644
index 0000000..00f8264
--- /dev/null
+++ b/src/rendering/textual/monochrome/short_action.rs
@@ -0,0 +1,75 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+use crate::core::context::general::GeneralContext;
+use crate::core::syntax::action::*;
+
+use crate::core::context::execution::ExecutionContext;
+
+
+pub fn action_to_text(action : &ObservableAction, gen_ctx : &GeneralContext, exe_ctx : &ExecutionContext) -> String {
+ let mut act_str : String = String::new();
+ // ***
+ let lf_name = gen_ctx.get_lf_name(action.lf_act.lf_id).unwrap();
+ act_str.push_str( &lf_name );
+ // ***
+ match &action.act_kind {
+ &ObservableActionKind::Reception => {
+ act_str.push_str("?");
+ },
+ &ObservableActionKind::Emission( ref targets ) => {
+ act_str.push_str("!");
+ if targets.len() > 0 {
+ act_str.push_str("(");
+ let mut count : usize = 0;
+ for tar_lf_act in targets {
+ let lf_name = gen_ctx.get_lf_name(tar_lf_act.lf_id).unwrap();
+ act_str.push_str( &lf_name );
+ count = count +1;
+ if count < targets.len() {
+ act_str.push_str(",");
+ }
+ }
+ act_str.push_str(")");
+ }
+ }
+ }
+ // ***
+ match gen_ctx.get_ms_name(action.ms_id) {
+ Err(e) => {
+ println!("WARNING action message name not found for display");
+ panic!();
+ },
+ Ok( ms_name ) => {
+ act_str.push_str( &ms_name );
+ }
+ }
+ // ***
+ let prm_num = action.params.len();
+ if prm_num > 0 {
+ act_str.push_str("(");
+ let mut current_prm : usize = 0;
+ for prm_arg in &action.params {
+ act_str.push_str( &exe_ctx.get_vr_name(gen_ctx,prm_arg.vr_id).unwrap() );
+ current_prm = current_prm +1;
+ if current_prm < prm_num {
+ act_str.push_str( "," );
+ }
+ }
+ act_str.push_str( ")" );
+ }
+ // ***
+ return act_str;
+}
\ No newline at end of file
diff --git a/src/rendering/textual/monochrome/trace.rs b/src/rendering/textual/monochrome/trace.rs
new file mode 100644
index 0000000..20411e6
--- /dev/null
+++ b/src/rendering/textual/monochrome/trace.rs
@@ -0,0 +1,114 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use regex::Regex;
+use crate::core::trace::*;
+use crate::core::syntax::action::*;
+
+
+pub fn trace_from_text(text : &str, lf_vec : &Vec<String>, ms_vec : &Vec<String>) -> IndexedTrace {
+ let re_splitter = Regex::new( r"\." ).unwrap();
+ let events_text : Vec<&str> = re_splitter.split( text ).collect();
+ //println!("text : {} - splitted : {:?}",text,events_text);
+ //
+ let mut trace : IndexedTrace = Vec::new();
+ for event_text in events_text {
+ trace.push( indexed_event_from_text(event_text, lf_vec, ms_vec) );
+ }
+ return trace;
+}
+
+
+
+
+fn parse_trace_parameters(parameters_as_str : &str) -> Vec<TraceParameter> {
+ let re_prms = Regex::new( r"," ).unwrap();
+ let prm_str_vec : Vec<&str> = re_prms.split(parameters_as_str).collect();
+ let mut prm_vec : Vec<TraceParameter> = Vec::new();
+ // ***
+ for prm_str in prm_str_vec {
+ prm_vec.push( TraceParameter::Raw(prm_str.to_string()) );
+ }
+ return prm_vec;
+}
+
+
+
+fn indexed_event_from_text(my_string : &str, lf_vec : &Vec<String>, ms_vec : &Vec<String>) -> IndexedEvent {
+ let emission_regex = Regex::new(REGEX_EMISSION).unwrap();
+ let reception_regex = Regex::new(REGEX_RECEPTION).unwrap();
+ //
+ if emission_regex.is_match(&my_string) {
+ let caps = emission_regex.captures(&my_string).unwrap();
+ let base_act_str : &str;
+ let arguments : Option<&str>;
+ match caps.get(1) {
+ None => {
+ base_act_str = &my_string;
+ arguments = None;
+ }
+ Some(cap1) => {
+ let arguments_with_parenthesis = cap1.as_str();
+ base_act_str = &my_string[..my_string.len() - arguments_with_parenthesis.len()];
+ arguments = Some(&arguments_with_parenthesis[1..arguments_with_parenthesis.len()-1]);
+ }
+ }
+ // ***
+ let re_emission = Regex::new( r"!" ).unwrap();
+ let (lf_id , ms_id) = get_lf_ms_ids(re_emission, base_act_str, lf_vec, ms_vec);
+ // ***
+ match arguments {
+ None => {
+ return IndexedEvent{lf_id:lf_id, evt_kind : SdEventKind::Emission, ms_id : ms_id, params : Vec::new()};
+ },
+ Some(parameters_as_str) => {
+ let params = parse_trace_parameters(parameters_as_str);
+ return IndexedEvent{lf_id:lf_id, evt_kind : SdEventKind::Emission, ms_id : ms_id, params : params};
+ }
+ }
+ } else if reception_regex.is_match(&my_string) {
+ let caps = reception_regex.captures(&my_string).unwrap();
+ let base_act_str : &str;
+ let arguments : Option<&str>;
+ match caps.get(1) {
+ None => {
+ base_act_str = &my_string;
+ arguments = None;
+ }
+ Some(cap1) => {
+ let arguments_with_parenthesis = cap1.as_str();
+ base_act_str = &my_string[..my_string.len() - arguments_with_parenthesis.len()];
+ arguments = Some(&arguments_with_parenthesis[1..arguments_with_parenthesis.len()-1]);
+ }
+ }
+ // ***
+ let re_reception = Regex::new( r"\?" ).unwrap();
+ let (lf_id , ms_id) = get_lf_ms_ids(re_reception, base_act_str, lf_vec, ms_vec);
+ // ***
+ match arguments {
+ None => {
+ return IndexedEvent{lf_id:lf_id, evt_kind : SdEventKind::Reception, ms_id : ms_id, params : Vec::new()};
+ },
+ Some(parameters_as_str) => {
+ let params = parse_trace_parameters(parameters_as_str);
+ return IndexedEvent{lf_id:lf_id, evt_kind : SdEventKind::Reception, ms_id : ms_id, params : params};
+ }
+ }
+ } else {
+ panic!("error while parsing trace");
+ }
+}
+
+
+
diff --git a/src/sd_syntax.pest b/src/sd_syntax.pest
new file mode 100644
index 0000000..3137bd9
--- /dev/null
+++ b/src/sd_syntax.pest
@@ -0,0 +1,294 @@
+/*******************************************************************************
+* Copyright (c) 2020, 2021 CentraleSupelec, CEA - LIST and others.
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+// ***********************************************
+// generic label ; used for variables, lifelines, messages, etc
+WHITESPACE = _{ " " | "\r\n" | "\n" | "\t" | "\r" }
+HIBOU_LABEL = @{ LETTER ~ (LETTER | ASCII_DIGIT | "_")* }
+// ***********************************************
+LIFELINE_LABEL = { HIBOU_LABEL }
+MESSAGE_LABEL = { HIBOU_LABEL }
+VAR_LABEL = { HIBOU_LABEL }
+PRM_LABEL = { HIBOU_LABEL }
+// ***********************************************
+// ***********************************************
+
+// Typing system
+
+// for declaring types of variables
+DATA_TYPE_Clock = { "Clock" }
+DATA_TYPE_Bool = { "Bool" }
+DATA_TYPE_Integer = { "Integer" }
+DATA_TYPE_Float = { "Float" }
+DATA_TYPE_String = { "String" }
+
+DATA_TYPE = _{ DATA_TYPE_Clock
+ | DATA_TYPE_Bool
+ | DATA_TYPE_Integer
+ | DATA_TYPE_Float
+ | DATA_TYPE_String
+ }
+
+// for declaring variables and refering to them by name
+
+VAR_DECLARATION = { VAR_LABEL ~ ":" ~ DATA_TYPE }
+
+HIBOU_MODEL_VAR_DECL = { "@variable" ~ "{" ~
+ VAR_DECLARATION ~ (";" ~ VAR_DECLARATION)*
+ ~ "}"}
+
+PRM_DECLARATION = { PRM_LABEL ~ ":" ~ DATA_TYPE }
+PR_DECL = _{ DATA_TYPE | PRM_DECLARATION }
+MSG_PR_DECL = { "(" ~ PR_DECL ~ ("," ~ PR_DECL )* ~ ")" }
+MESSAGE_DECLARATION = { MESSAGE_LABEL ~ MSG_PR_DECL? }
+HIBOU_MODEL_MS_DECL = { "@message" ~ "{" ~
+ MESSAGE_DECLARATION ~ (";" ~ MESSAGE_DECLARATION)*
+ ~ "}"}
+
+HIBOU_MODEL_LF_DECL = { "@lifeline" ~ "{" ~
+ LIFELINE_LABEL ~ (";" ~ LIFELINE_LABEL)* ~ "}"}
+
+VAR_INIT = { LIFELINE_LABEL ~ "." ~ VAR_LABEL ~ "=" ~ TD_VALUE_OR_NEW_FRESH }
+
+HIBOU_MODEL_VAR_INIT = { "@init" ~ "{" ~
+ VAR_INIT ~ (";" ~ VAR_INIT)*
+ ~ "}"}
+
+// ***********************************************
+
+// numbers and basic arithmetics
+ARITH_INTEGER = { "0" | (ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) }
+ARITH_FLOAT_decimal = { ASCII_DIGIT* }
+ARITH_FLOAT = { ARITH_INTEGER ~ "." ~ ARITH_FLOAT_decimal }
+
+ARITH_NUMBER = _{ ARITH_FLOAT | ARITH_INTEGER }
+ARITH_PLUS = { "+" }
+ARITH_MINUS = { "-" }
+ARITH_MULT = { "*" }
+ARITH_DIV = { "/" }
+
+ARITH_EXPR = { ARITH_FACTOR ~ ARITH_ADD_EXPR* }
+ARITH_ADD_EXPR = { (ARITH_PLUS|ARITH_MINUS) ~ ARITH_FACTOR }
+ARITH_FACTOR = { ARTIH_PRIMARY ~ ARITH_MULT_EXPR* }
+ARITH_MULT_EXPR = { (ARITH_MULT|ARITH_DIV) ~ ARTIH_PRIMARY }
+ARTIH_PRIMARY = { "(" ~ ARITH_EXPR ~ ")"
+ | ARITH_NUMBER
+ | MSG_PRM_REF
+ | VAR_LABEL
+ | ARITH_MINUS ~ ARTIH_PRIMARY }
+
+// booleans and basic logic
+LOGIC_FALSE = { "⊥" }
+LOGIC_TRUE = { "⊤" }
+
+LOGIC_SYMB_Diff = { "!=" | "≠" }
+LOGIC_SYMB_E = { "==" | "=" }
+LOGIC_SYMB_G = { ">" }
+LOGIC_SYMB_GoE = {">=" | "≥"}
+LOGIC_SYMB_L = { "<" }
+LOGIC_SYMB_LoE = { "<=" | "≤" }
+LOGIC_SYMB_CMP = _{ LOGIC_SYMB_Diff
+ | LOGIC_SYMB_E
+ | LOGIC_SYMB_GoE
+ | LOGIC_SYMB_G
+ | LOGIC_SYMB_LoE
+ | LOGIC_SYMB_L
+ }
+
+LOGIC_SYMB_AND = { ("/\\" | "∧" ) }
+LOGIC_SYMB_OR = { ("\\/" | "∨" ) }
+LOGIC_NOT = { ("¬"|"!") ~ LOGIC_EXPR }
+LOGIC_AND = { LOGIC_EXPR ~ (LOGIC_SYMB_AND ~ LOGIC_EXPR)+ }
+LOGIC_OR = { LOGIC_EXPR ~ (LOGIC_SYMB_OR ~ LOGIC_EXPR)+ }
+LOGIC_CMP = { TD_VALUE ~ LOGIC_SYMB_CMP ~ TD_VALUE }
+LOGIC_EXPR = { LOGIC_NOT
+ | "(" ~ LOGIC_AND ~ ")"
+ | "(" ~ LOGIC_OR ~ ")"
+ | "(" ~ LOGIC_CMP ~ ")"
+ | MSG_PRM_REF
+ | VAR_LABEL
+ | LOGIC_FALSE
+ | LOGIC_TRUE}
+
+// strings
+STRING_content = { (!"\"" ~ ANY)* }
+STRING = _{ "\"" ~ STRING_content ~ "\"" }
+
+// everything put together for variable terms
+
+MSG_PRM_REF = { "$" ~ (PRM_LABEL|ARITH_INTEGER) }
+TD_VALUE = { STRING
+ | MSG_PRM_REF
+ | VAR_LABEL
+ | ARITH_EXPR
+ | LOGIC_EXPR
+ }
+
+// ***********************************************
+
+
+// Sequence Diagrams
+
+SD_GUARD = { "[" ~ LOGIC_EXPR ~ (";" ~ LOGIC_EXPR)* ~ "]" }
+
+NEW_FRESH = { "※" | "#" }
+TD_VALUE_OR_NEW_FRESH = _{ TD_VALUE | NEW_FRESH }
+OPERATION_ASSIGNMENT = { VAR_LABEL ~ ":=" ~ TD_VALUE_OR_NEW_FRESH }
+OPERATION_RESET = { "reset " ~ VAR_LABEL }
+SD_OPERATION_content = _{ OPERATION_ASSIGNMENT
+ | OPERATION_RESET
+ }
+
+SD_OPERATION = { "{" ~ SD_OPERATION_content ~ (";" ~ SD_OPERATION_content)* ~ "}" }
+
+SD_ACTION_AMBLE = {(SD_OPERATION|SD_GUARD)+}
+
+//
+
+SD_MESSAGE_PARAMETERS = { "(" ~ TD_VALUE_OR_NEW_FRESH ~ ("," ~ TD_VALUE_OR_NEW_FRESH)* ~ ")" }
+
+SD_LIFELINE_ACTION = { SD_ACTION_AMBLE? ~ LIFELINE_LABEL ~ SD_ACTION_AMBLE? }
+SD_EMISSION_TARGETS = { "(" ~ SD_LIFELINE_ACTION ~ ("," ~ SD_LIFELINE_ACTION)* ~ ")" }
+SD_EMISSION_TARGET = { SD_LIFELINE_ACTION | SD_EMISSION_TARGETS }
+SD_ACTION_EMISSION = { SD_LIFELINE_ACTION ~ "--" ~
+ MESSAGE_LABEL ~
+ SD_MESSAGE_PARAMETERS?
+ ~ "->" ~ (SD_EMISSION_TARGET | "|")}
+
+SD_ACTION_RECEPTION = { ("|" ~ "--")? ~ MESSAGE_LABEL ~
+ SD_MESSAGE_PARAMETERS?
+ ~ "->" ~ SD_LIFELINE_ACTION}
+
+SD_EMPTY_INTERACTION = {"o" | "∅"}
+
+SD_STRICT = {"@strict"}
+SD_STRICT_INT = { SD_STRICT ~ "(" ~ SD_INTERACTION ~ ( "," ~ SD_INTERACTION)+ ~ ")" }
+
+SD_SEQ = {"@seq"}
+SD_SEQ_INT = { SD_SEQ ~ "(" ~ SD_INTERACTION ~ ( "," ~ SD_INTERACTION)+ ~ ")" }
+
+SD_ALT = {"@alt"}
+SD_ALT_INT = { SD_ALT ~ "(" ~ SD_INTERACTION ~ ( "," ~ SD_INTERACTION)+ ~ ")" }
+
+SD_PAR = {"@par"}
+SD_PAR_INT = { SD_PAR ~ "(" ~ SD_INTERACTION ~ ( "," ~ SD_INTERACTION)+ ~ ")" }
+
+SD_LOOP_STRICT = {"@loop_strict"}
+SD_LOOP_SEQ = {"@loop_seq"}
+SD_LOOP_PAR = {"@loop_par"}
+SD_LOOP_INT = { (SD_LOOP_STRICT | SD_LOOP_SEQ | SD_LOOP_PAR) ~ "(" ~ SD_INTERACTION ~ ")" }
+
+SD_SCOPE = {"@scope"}
+SD_SCOPED_PARAMS = { VAR_LABEL ~ ("," ~ VAR_LABEL)* }
+SD_SCOPE_INT = { SD_SCOPE ~ "{" ~ SD_SCOPED_PARAMS ~ "}" ~ "(" ~ SD_INTERACTION ~ ")" }
+
+SD_INTERACTION = { SD_EMPTY_INTERACTION
+ | SD_ACTION_RECEPTION
+ | SD_ACTION_EMISSION
+ | SD_STRICT_INT
+ | SD_SEQ_INT
+ | SD_ALT_INT
+ | SD_PAR_INT
+ | SD_LOOP_INT
+ | SD_SCOPE_INT
+ }
+
+// ***********************************************
+// ***********************************************
+// ***********************************************
+// ***** hibou options
+GRAPHIC_LOGGER_KIND_png = { "png" }
+GRAPHIC_LOGGER_KIND_svg = { "svg" }
+OPTION_GRAPHIC_LOGGER = { "graphic" ~ ( "=" ~ (GRAPHIC_LOGGER_KIND_png|GRAPHIC_LOGGER_KIND_svg) )? }
+OPTION_LOGGER_KIND = _{ OPTION_GRAPHIC_LOGGER }
+OPTION_LOGGER_DECL = { "loggers" ~ "=" ~ "[" ~ OPTION_LOGGER_KIND ~ ("," ~ OPTION_LOGGER_KIND)* ~ "]" }
+// ***********************************************
+OPTION_STRATEGY_BFS = { "BFS" }
+OPTION_STRATEGY_DFS = { "DFS" }
+OPTION_STRATEGY_KIND = _{ OPTION_STRATEGY_BFS | OPTION_STRATEGY_DFS }
+OPTION_STRATEGY_DECL = { "strategy" ~ "=" ~ OPTION_STRATEGY_KIND }
+// ***********************************************
+// ***********************************************
+OPTION_PREFILTER_MAX_DEPTH = { "max_depth" ~ "=" ~ ARITH_INTEGER }
+OPTION_PREFILTER_MAX_LOOP_DEPTH = { "max_loop_depth" ~ "=" ~ ARITH_INTEGER }
+OPTION_PREFILTER_MAX_NODE_NUMBER = { "max_node_number" ~ "=" ~ ARITH_INTEGER }
+OPTION_PREFILTER = _{ OPTION_PREFILTER_MAX_DEPTH | OPTION_PREFILTER_MAX_LOOP_DEPTH | OPTION_PREFILTER_MAX_NODE_NUMBER }
+OPTION_PREFILTERS_DECL = { "pre_filters" ~ "=" ~ "[" ~ OPTION_PREFILTER ~ ("," ~ OPTION_PREFILTER)* ~ "]" }
+// ***********************************************
+OPTION_PRIORITTY_emission = { "emission" }
+OPTION_PRIORITTY_reception = { "reception" }
+OPTION_PRIORITY_loop = { "loop" }
+OPTION_PRIORITY_KIND = _{ OPTION_PRIORITTY_emission | OPTION_PRIORITTY_reception | OPTION_PRIORITY_loop }
+OPTION_PRIORITY_LEVEL = { ARITH_INTEGER | ("-" ~ ARITH_INTEGER ) }
+OPTION_PRIORITY = { OPTION_PRIORITY_KIND ~ "=" ~ OPTION_PRIORITY_LEVEL }
+OPTION_PRIORITIES_DECL = { "frontier_priorities" ~ "=" ~ "[" ~ OPTION_PRIORITY ~ ("," ~ OPTION_PRIORITY)* ~ "]" }
+// ***********************************************
+OPTION_TEMPORALITY_TIMED = { "temporality" ~ "=" ~ "timed" }
+OPTION_TEMPORALITY_UNTIMED = { "temporality" ~ "=" ~ "untimed" }
+OPTION_TEMPORALITY = _{ OPTION_TEMPORALITY_TIMED | OPTION_TEMPORALITY_UNTIMED }
+// ***********************************************
+GENERAL_OPTION_DECL = _{ OPTION_TEMPORALITY | OPTION_LOGGER_DECL | OPTION_STRATEGY_DECL | OPTION_PREFILTERS_DECL | OPTION_PRIORITIES_DECL }
+// ***********************************************
+EXPLORE_OPTION_DECL = _{ GENERAL_OPTION_DECL }
+EXPLORE_OPTION_SECTION = { "@explore_option" ~ "{" ~
+ EXPLORE_OPTION_DECL ~ (";" ~ EXPLORE_OPTION_DECL)*
+ ~ "}"}
+// ***********************************************
+OPTION_GOAL_pass = { "Pass" }
+OPTION_GOAL_weakpass = { "WeakPass" }
+OPTION_GOAL_KIND = _{ OPTION_GOAL_pass | OPTION_GOAL_weakpass }
+OPTION_GOAL_DECL = { "goal" ~ "=" ~ OPTION_GOAL_KIND }
+// ***********************************************
+ANALYZE_OPTION_DECL = _{ GENERAL_OPTION_DECL | OPTION_GOAL_DECL }
+ANALYZE_OPTION_SECTION = { "@analyze_option" ~ "{" ~
+ ANALYZE_OPTION_DECL ~ (";" ~ ANALYZE_OPTION_DECL)*
+ ~ "}"}
+// ***********************************************
+// ***********************************************
+// setup & .hsf file
+
+SETUP_SECTION = _{ EXPLORE_OPTION_SECTION | ANALYZE_OPTION_SECTION | HIBOU_MODEL_MS_DECL | HIBOU_MODEL_LF_DECL | HIBOU_MODEL_VAR_DECL | HIBOU_MODEL_VAR_INIT }
+HIBOU_MODEL_SETUP = { SETUP_SECTION* }
+HSF_PEST_FILE = { SOI ~
+ HIBOU_MODEL_SETUP ~ SD_INTERACTION ~
+ EOI }
+
+// ***********************************************
+// ***********************************************
+// traces & multitraces
+TRACE_LIFELINE = { HIBOU_LABEL }
+TRACE_MESSAGE = { HIBOU_LABEL }
+
+TRACE_EMISSION_SYMBOL = { "!" }
+TRACE_RECEPTION_SYMBOL = { "?" }
+
+TRACE_LOGIC = _{ LOGIC_FALSE | LOGIC_TRUE }
+
+TRACE_ARGUMENT = { STRING | TRACE_LOGIC | ARITH_FLOAT | ARITH_INTEGER }
+
+TRACE_ARGUMENTS = { "(" ~ TRACE_ARGUMENT ~ ("," ~ TRACE_ARGUMENT)* ~ ")" }
+TRACE_DELAY = { "[" ~ ARITH_FLOAT ~ "]" }
+TRACE_ACTION = { TRACE_DELAY? ~ TRACE_LIFELINE ~ (TRACE_EMISSION_SYMBOL|TRACE_RECEPTION_SYMBOL) ~ TRACE_MESSAGE ~ TRACE_ARGUMENTS? }
+// ***********************************************
+CANAL_LIFELINES = { TRACE_LIFELINE ~ ("," ~ TRACE_LIFELINE)* }
+CANAL_ANY = {"#any"}
+CANAL_ALL = {"#all"}
+TRACE_CANAL = _{ "[" ~ (CANAL_ANY | CANAL_ALL | CANAL_LIFELINES) ~ "]" }
+TRACE = { TRACE_CANAL ~ (TRACE_ACTION ~ ("." ~ TRACE_ACTION)*)? }
+// ***********************************************
+MULTI_TRACE = { "{" ~ (TRACE ~ (";" ~ TRACE)* )? ~ "}" }
+// ***********************************************
+HTF_PEST_FILE = { SOI ~ (MULTI_TRACE|TRACE) ~ EOI }
+// ***********************************************
\ No newline at end of file
diff --git a/src/test_cli_replace.rs b/src/test_cli_replace.rs
new file mode 100644
index 0000000..cbd02ed
--- /dev/null
+++ b/src/test_cli_replace.rs
@@ -0,0 +1,87 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashSet;
+use std::fs::write;
+use std::path::Path;
+use clap::App;
+use clap::ArgMatches;
+
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::trace::*;
+
+
+
+
+use crate::rendering::custom_draw::seqdiag::interaction::draw_interaction;
+
+
+use crate::rendering::process::graphic_logger::GraphicProcessLogger;
+
+use crate::process::log::*;
+use crate::process::exploration::explore;
+use crate::process::analysis::analyze;
+use crate::from_text::hsf_file::{ProcessKind,parse_hsf_file};
+use crate::from_text::htf_file::parse_htf_file;
+use crate::process::hibou_process::HibouSearchStrategy;
+
+
+
+pub async fn test_explore(name : &str) {
+ let hsf_file_path = name.to_string();
+ match parse_hsf_file(&hsf_file_path, &ProcessKind::Explore) {
+ Err(e) => {
+ println!("{}", "error parsing .hsf file".to_string() );
+ println!("{}", e.to_string() );
+ },
+ Ok( (gen_ctx,exe_ctx,my_int,mut hoptions) ) => {
+ explore(my_int, gen_ctx, exe_ctx,hoptions.temporality,hoptions.pre_filters, hoptions.strategy,hoptions.frontier_priorities,hoptions.loggers).await;
+ }
+ }
+}
+
+pub async fn test_analyze(hsfname : &str, htfname : &str) {
+ let hsf_file_path = hsfname.to_string();
+ match parse_hsf_file(&hsf_file_path,&ProcessKind::Analyze) {
+ Err(e) => {
+ println!("{}", "error parsing .hsf file".to_string() );
+ println!("{}", e.to_string() );
+ },
+ Ok( (gen_ctx,exe_ctx,my_int,mut hoptions) ) => {
+ let htf_file_path = htfname.to_string();
+ match parse_htf_file(&htf_file_path,&gen_ctx,&hoptions.temporality) {
+ Err(e) => {
+ println!("{}", "error parsing .htf file".to_string() );
+ println!("{}", e.to_string() );
+ },
+ Ok( multi_trace ) => {
+ let verdict = analyze(my_int,
+ multi_trace,
+ gen_ctx,
+ exe_ctx,
+ hoptions.temporality,
+ hoptions.pre_filters,
+ hoptions.strategy,
+ hoptions.frontier_priorities,
+ hoptions.loggers,
+ hoptions.goal.unwrap()).await;
+ println!("{}", format!("got verdict {:}", verdict.to_string()));
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/tools.rs b/src/tools.rs
new file mode 100644
index 0000000..748a166
--- /dev/null
+++ b/src/tools.rs
@@ -0,0 +1,29 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::fmt::Write;
+use std::fmt::Display;
+
+
+pub fn powerset<T>(s: &[T]) -> Vec<Vec<T>> where T: Clone {
+ (0..2usize.pow(s.len() as u32)).map(|i| {
+ s.iter().enumerate().filter(|&(t, _)| (i >> t) % 2 == 1)
+ .map(|(_, element)| element.clone())
+ .collect()
+ }).collect()
+}
+
+pub fn fold_vec_to_string<T: Display>(my_vec : &Vec<T>) -> String {
+ my_vec.iter().fold(String::new(),|mut s,n| {write!(s,"{}",n).ok(); s})
+}
diff --git a/src/ui/hibou_cli.rs b/src/ui/hibou_cli.rs
new file mode 100644
index 0000000..d7d9ca9
--- /dev/null
+++ b/src/ui/hibou_cli.rs
@@ -0,0 +1,184 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashSet;
+use std::fs::write;
+use std::path::Path;
+use clap::App;
+use clap::ArgMatches;
+
+
+use crate::core::context::general::GeneralContext;
+
+use crate::core::trace::*;
+
+
+
+
+use crate::rendering::custom_draw::seqdiag::interaction::draw_interaction;
+
+
+use crate::rendering::process::graphic_logger::GraphicProcessLogger;
+
+use crate::process::log::*;
+
+use crate::process::analysis::analyze;
+use crate::process::exploration::explore;
+use crate::from_text::hsf_file::{ProcessKind,parse_hsf_file};
+use crate::from_text::htf_file::parse_htf_file;
+
+fn get_ascii_border() -> &'static str {
+ return r#"===================="#;
+}
+
+fn get_ascii_left() -> Vec<&'static str> {
+ let mut my_vec = Vec::new();
+ my_vec.push(r#" ___ Holistic "#);
+ my_vec.push(r#"(o,o) Interaction"#);
+ my_vec.push(r#"{`"'} Behavioral "#);
+ my_vec.push(r#"-"-"- Oracle "#);
+ my_vec.push(r#" \_/ Utility "#);
+ my_vec.push(r#" "#);
+ my_vec.push(r#" V-efm-2020-10 "#);
+ return my_vec;
+}
+
+fn print_retval(ret_print : Vec<String>) {
+ let ascii_left = get_ascii_left();
+ // ***
+ println!("{}", get_ascii_border());
+ if ret_print.len() >= ascii_left.len() {
+ for i in 0..ascii_left.len() {
+ println!("{} | {}", ascii_left[i], ret_print[i]);
+ }
+ for i in ascii_left.len()..ret_print.len() {
+ println!("{} | {}", " ".repeat(19), ret_print[i]);
+ }
+ } else {
+ for i in 0..ret_print.len() {
+ println!("{} | {}", ascii_left[i], ret_print[i]);
+ }
+ for i in ret_print.len()..ascii_left.len() {
+ println!("{} |", ascii_left[i]);
+ }
+ }
+ println!("{}", get_ascii_border());
+}
+
+
+
+pub async fn hibou_cli() -> i32 {
+
+ let yaml = load_yaml!("hibou_cli.yml");
+ let matches = App::from_yaml(yaml).get_matches();
+
+ let mut ret_print : Vec<String> = Vec::new();
+
+ if let Some(matches) = matches.subcommand_matches("draw") {
+ let hsf_file_path = matches.value_of("hsf").unwrap();
+ match parse_hsf_file(hsf_file_path,&ProcessKind::None) {
+ Err(e) => {
+ ret_print.push( e.to_string() );
+ print_retval(ret_print);
+ return -1;
+ },
+ Ok( (gen_ctx,exe_ctx,my_int,hoptions) ) => {
+ let spec_output_file : String;
+ if matches.is_present("output") {
+ let extracted = matches.value_of("output").unwrap();
+ spec_output_file = format!("{}.png", extracted);
+ } else {
+ let file_name = Path::new(hsf_file_path).file_stem().unwrap().to_str().unwrap();
+ spec_output_file = format!("{}.png", file_name);
+ }
+ ret_print.push( "".to_string());
+ ret_print.push( "DRAWING INTERACTION".to_string());
+ ret_print.push( format!("from file '{}'",hsf_file_path) );
+ ret_print.push( format!("on file : {}",spec_output_file) );
+ ret_print.push( "".to_string());
+ draw_interaction(&spec_output_file, &my_int,&gen_ctx,&exe_ctx, &None);
+ }
+ }
+ } else if let Some(matches) = matches.subcommand_matches("explore") {
+ let hsf_file_path = matches.value_of("hsf").unwrap();
+ match parse_hsf_file(hsf_file_path,&ProcessKind::Explore) {
+ Err(e) => {
+ ret_print.push( e.to_string() );
+ print_retval(ret_print);
+ return -1;
+ },
+ Ok( (gen_ctx,exe_ctx,my_int,hoptions) ) => {
+ // ***
+ ret_print.push( "".to_string());
+ ret_print.push( "EXPLORING SEMANTICS".to_string());
+ ret_print.push( format!("of interaction from file '{}'",hsf_file_path) );
+ ret_print.push( "".to_string());
+ // ***
+ explore(my_int,
+ gen_ctx,exe_ctx,
+ hoptions.temporality,
+ hoptions.pre_filters,
+ hoptions.strategy,
+ hoptions.frontier_priorities,
+ hoptions.loggers).await;
+ }
+ }
+ } else if let Some(matches) = matches.subcommand_matches("analyze") {
+ let hsf_file_path = matches.value_of("hsf").unwrap();
+ match parse_hsf_file(hsf_file_path,&ProcessKind::Analyze) {
+ Err(e) => {
+ ret_print.push( e.to_string() );
+ print_retval(ret_print);
+ return -1;
+ },
+ Ok( (gen_ctx,exe_ctx,my_int,hoptions) ) => {
+ let htf_file_path = matches.value_of("htf").unwrap();
+ match parse_htf_file(htf_file_path,&gen_ctx,&hoptions.temporality) {
+ Err(e) => {
+ ret_print.push( e.to_string() );
+ print_retval(ret_print);
+ return -1;
+ },
+ Ok( multi_trace ) => {
+ ret_print.push( "ANALYZING TRACE".to_string());
+ ret_print.push( format!("from file '{}'",htf_file_path) );
+ ret_print.push( "W.R.T. INTERACTION".to_string());
+ ret_print.push( format!("from file '{}'",hsf_file_path) );
+ ret_print.push( "".to_string());
+
+ let verdict = analyze(my_int,
+ multi_trace,
+ gen_ctx,
+ exe_ctx,
+ hoptions.temporality,
+ hoptions.pre_filters,
+ hoptions.strategy,
+ hoptions.frontier_priorities,
+ hoptions.loggers,
+ hoptions.goal.unwrap()).await;
+
+ ret_print.push( format!("verdict: '{}'", verdict.to_string() ) );
+ }
+ }
+ }
+ }
+ } else {
+ ret_print.push( "".to_string() );
+ ret_print.push( "TYPE help or -h to get a summary of the utilities".to_string() );
+ }
+ // ***
+ print_retval(ret_print);
+ return 0;
+}
+
diff --git a/src/ui/hibou_cli.yml b/src/ui/hibou_cli.yml
new file mode 100644
index 0000000..41967fd
--- /dev/null
+++ b/src/ui/hibou_cli.yml
@@ -0,0 +1,58 @@
+#
+# Copyright (c) 2020, 2021 CentraleSupelec, CEA - LIST and others.
+#
+# This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License 2.0
+# which accompanies this distribution, and is available at
+# https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+# Contributors:
+# Erwan Mahé (CentraleSupelec) - initial API and implementation
+#
+
+
+
+
+name: hibou_efm
+version: "0.1.0"
+author: Erwan Mahe <github.com/erwanM974>
+about: Holistic Interaction Behavioral Oracle Utility - hibou provides utilities for the analysis of traces and multi-traces of interaction models (sequence diagrams/sequence charts)
+subcommands:
+ - draw:
+ about: utility to draw as a sequence diagram an input hibou specification file (.hsf)
+ version: "0.1.0"
+ author: Erwan Mahe <github.com/erwanM974>
+ args:
+ - hsf:
+ required: true
+ index: 1
+ help: hibou specification file
+ - output:
+ required: false
+ short: o
+ takes_value: true
+ help: target file for drawing (default is 'the name of the hsf'.png)
+ - explore:
+ about: utility to explore the semantics of an input hibou specification file (.hsf)
+ version: "0.1.0"
+ author: Erwan Mahe <github.com/erwanM974>
+ args:
+ - hsf:
+ required: true
+ index: 1
+ help: hibou specification file
+ - analyze:
+ about: utility to analyze an input (multi-)trace from a hibou trace file (.htf) w.r.t. an input hibou specification file (.hsf)
+ version: "0.1.0"
+ author: Erwan Mahe <github.com/erwanM974>
+ args:
+ - hsf:
+ required: true
+ index: 1
+ help: hibou specification file
+ - htf:
+ required: true
+ index: 2
+ help: hibou trace file
\ No newline at end of file
diff --git a/src/ui/mod.rs b/src/ui/mod.rs
new file mode 100644
index 0000000..2a86eef
--- /dev/null
+++ b/src/ui/mod.rs
@@ -0,0 +1,15 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+pub mod hibou_cli;
diff --git a/src/xlia/data.rs b/src/xlia/data.rs
new file mode 100644
index 0000000..7dd9ef5
--- /dev/null
+++ b/src/xlia/data.rs
@@ -0,0 +1,296 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::fmt::Write;
+
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+
+use crate::core::syntax::data::var_ref::VariableReference;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::builtin::bool::*;
+use crate::core::syntax::data::builtin::number::*;
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::float::TD_Float;
+use crate::core::syntax::data::builtin::string::TD_String;
+
+use crate::xlia::xlia_build_name_tools::*;
+
+pub fn td_generic_to_xlia(gen_ctx : &GeneralContext, td_gen : &TD_Generic) -> String {
+ match td_gen {
+ TD_Generic::Bool(td_bool) => {
+ return td_bool_to_xlia(gen_ctx, td_bool);
+ },
+ TD_Generic::String(td_string) => {
+ return td_string_to_xlia(gen_ctx, td_string);
+ },
+ TD_Generic::Integer(td_int) => {
+ return td_int_to_xlia(gen_ctx, td_int);
+ },
+ TD_Generic::Float(td_float) => {
+ return td_float_to_xlia(gen_ctx, td_float);
+ }
+ }
+}
+
+fn var_ref_to_xlia(gen_ctx : &GeneralContext, var_ref : &VariableReference) -> String {
+ match var_ref {
+ VariableReference::VARIABLE( var_id ) => {
+ return variable_diversity_name(gen_ctx,*var_id);
+ },
+ VariableReference::MSG_PARAMETER( ms_id, pr_id) => {
+ return message_parameter_diversity_name(gen_ctx,*ms_id,*pr_id);
+ },
+ _ => {
+ panic!();
+ }
+ }
+}
+
+
+
+fn td_int_to_xlia(gen_ctx : &GeneralContext, td_int : &TD_Integer) -> String {
+ match td_int {
+ TD_Integer::Value( value ) => {
+ return value.to_string();
+ },
+ TD_Integer::Reference(var_ref) => {
+ return var_ref_to_xlia(gen_ctx,var_ref);
+ },
+ TD_Integer::Minus( minused ) => {
+ let minused_td_int = td_int_to_xlia(gen_ctx,&*minused);
+ return format!("- {}",minused_td_int);
+ }
+ TD_Integer::Add( adds ) => {
+ let mut operand = String::new();
+ let mut first : bool = true;
+ for (add_sign,sub_int) in adds {
+ let sub_int_expr = td_int_to_xlia(gen_ctx,sub_int);
+ match add_sign {
+ ARITH_ADD_SIGN::Plus => {
+ if first {
+ operand.push_str( &sub_int_expr );
+ first = false;
+ } else {
+ operand.push_str( &format!("+ {}",sub_int_expr) );
+ }
+ },
+ ARITH_ADD_SIGN::Minus => {
+ if first {
+ first = false;
+ }
+ operand.push_str( &format!("- {}",sub_int_expr) );
+ }
+ }
+ }
+ return operand;
+ },
+ TD_Integer::Factor( factor ) => {
+ let mut operand = String::new();
+ let mut first : bool = true;
+ for (add_sign,sub_int) in factor {
+ let sub_int_expr = td_int_to_xlia(gen_ctx,sub_int);
+ match add_sign {
+ ARITH_FACTOR_SIGN::Mult => {
+ if first {
+ operand.push_str( &sub_int_expr );
+ first = false;
+ } else {
+ operand.push_str( &format!("* {}",sub_int_expr) );
+ }
+ },
+ ARITH_FACTOR_SIGN::Div => {
+ if first {
+ first = false;
+ operand.push_str( &format!("(1/{})",sub_int_expr) );
+ } else {
+ operand.push_str( &format!("* (1/{})",sub_int_expr) );
+ }
+ }
+ }
+ }
+ return operand;
+ }
+ }
+}
+
+fn print_float(my_float : f64) -> String {
+ let left_str = my_float.to_string();
+ if left_str.contains(".") {
+ return left_str;
+ } else {
+ return format!("{}.0",&left_str);
+ }
+}
+
+fn td_float_to_xlia(gen_ctx : &GeneralContext, td_float : &TD_Float) -> String {
+ match td_float {
+ TD_Float::Value( value ) => {
+ return print_float(*value);
+ },
+ TD_Float::Reference(var_ref) => {
+ return var_ref_to_xlia(gen_ctx,var_ref);
+ },
+ TD_Float::Minus( minused ) => {
+ let minused_td_int = td_float_to_xlia(gen_ctx,&*minused);
+ return format!("- {}",minused_td_int);
+ }
+ TD_Float::Add( adds ) => {
+ let mut operand = String::new();
+ let mut first : bool = true;
+ for (add_sign,sub_int) in adds {
+ let sub_int_expr = td_float_to_xlia(gen_ctx,sub_int);
+ match add_sign {
+ ARITH_ADD_SIGN::Plus => {
+ if first {
+ operand.push_str( &sub_int_expr );
+ first = false;
+ } else {
+ operand.push_str( &format!("+ {}",sub_int_expr) );
+ }
+ },
+ ARITH_ADD_SIGN::Minus => {
+ if first {
+ first = false;
+ }
+ operand.push_str( &format!("- {}",sub_int_expr) );
+ }
+ }
+ }
+ return operand;
+ },
+ TD_Float::Factor( factor ) => {
+ let mut operand = String::new();
+ let mut first : bool = true;
+ for (add_sign,sub_int) in factor {
+ let sub_int_expr = td_float_to_xlia(gen_ctx,sub_int);
+ match add_sign {
+ ARITH_FACTOR_SIGN::Mult => {
+ if first {
+ operand.push_str( &sub_int_expr );
+ first = false;
+ } else {
+ operand.push_str( &format!("* {}",sub_int_expr) );
+ }
+ },
+ ARITH_FACTOR_SIGN::Div => {
+ if first {
+ first = false;
+ operand.push_str( &format!("(1.0/{})",sub_int_expr) );
+ } else {
+ operand.push_str( &format!("* (1.0/{})",sub_int_expr) );
+ }
+ }
+ }
+ }
+ return operand;
+ }
+ }
+}
+
+fn td_string_to_xlia(gen_ctx : &GeneralContext, td_string : &TD_String) -> String {
+ match td_string {
+ TD_String::Reference(var_ref) => {
+ return var_ref_to_xlia(gen_ctx,var_ref);
+ },
+ TD_String::Value( value ) => {
+ return format!("\"{}\"",value);
+ }
+ }
+}
+
+
+pub fn td_bool_to_xlia(gen_ctx : &GeneralContext, td_bool : &TD_Bool) -> String {
+ match td_bool {
+ TD_Bool::TRUE => {
+ return "true".to_string();
+ },
+ TD_Bool::FALSE => {
+ return "false".to_string();
+ },
+ TD_Bool::AND(sub_bools) => {
+ let mut and_string = String::new();
+ let mut first : bool = true;
+ for sub_bool in sub_bools {
+ let sub_string = td_bool_to_xlia(gen_ctx,sub_bool);
+ if first {
+ first = false;
+ and_string.push_str(&sub_string);
+ } else {
+ and_string.push_str(" && ");
+ and_string.push_str(&sub_string);
+ }
+ }
+ return and_string;
+ /*
+ let mut sub_exprs : Vec<String> = Vec::new();
+ for sub_bool in sub_bools {
+ sub_exprs.push( td_bool_to_xlia(gen_ctx,sub_bool) );
+ }
+ return sub_exprs.iter().fold(String::new(),|mut s,n| {write!(s," && {}",n).ok(); s});*/
+ },
+ TD_Bool::OR(sub_bools) => {
+ /*
+ let mut sub_exprs : Vec<String> = Vec::new();
+ for sub_bool in sub_bools {
+ sub_exprs.push( td_bool_to_xlia(gen_ctx,sub_bool) );
+ }
+ return sub_exprs.iter().fold(String::new(),|mut s,n| {write!(s," || {}",n).ok(); s});*/
+ let mut and_string = String::new();
+ let mut first : bool = true;
+ for sub_bool in sub_bools {
+ let sub_string = td_bool_to_xlia(gen_ctx,sub_bool);
+ if first {
+ first = false;
+ and_string.push_str(&sub_string);
+ } else {
+ and_string.push_str(" || ");
+ and_string.push_str(&sub_string);
+ }
+ }
+ return and_string;
+ },
+ TD_Bool::NOT(sub_bool) => {
+ return format!("not {}", td_bool_to_xlia(gen_ctx,sub_bool));
+ },
+ TD_Bool::COMPARE(bool_compare,first,second) => {
+ let first_expression = td_generic_to_xlia(gen_ctx,&*first);
+ let second_expression = td_generic_to_xlia(gen_ctx,&*second);
+ match bool_compare {
+ Bool_Compare::Equal => {
+ return format!("{} == {}", first_expression, second_expression);
+ },
+ Bool_Compare::Different => {
+ return format!("{} != {}", first_expression, second_expression);
+ },
+ Bool_Compare::Greater => {
+ return format!("{} > {}", first_expression, second_expression);
+ },
+ Bool_Compare::GreaterOrEqual => {
+ return format!("{} >= {}", first_expression, second_expression);
+ },
+ Bool_Compare::Lower => {
+ return format!("{} < {}", first_expression, second_expression);
+ },
+ Bool_Compare::LowerOrEqual => {
+ return format!("{} <= {}", first_expression, second_expression);
+ }
+ }
+ },
+ TD_Bool::Reference( var_ref ) => {
+ return var_ref_to_xlia(gen_ctx,var_ref);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/xlia/mod.rs b/src/xlia/mod.rs
new file mode 100644
index 0000000..3c6940d
--- /dev/null
+++ b/src/xlia/mod.rs
@@ -0,0 +1,20 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+
+
+mod xlia_build_name_tools;
+pub mod data;
+pub mod model;
+mod model_initialization;
\ No newline at end of file
diff --git a/src/xlia/model.rs b/src/xlia/model.rs
new file mode 100644
index 0000000..11d8e7e
--- /dev/null
+++ b/src/xlia/model.rs
@@ -0,0 +1,431 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashMap;
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::interaction::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::td_type::TD_DataType;
+
+use crate::tools::fold_vec_to_string;
+
+use crate::xlia::xlia_build_name_tools::*;
+use crate::xlia::data::{td_generic_to_xlia,td_bool_to_xlia};
+use crate::xlia::model_initialization::make_lifeline_initialization_action;
+use crate::process::hibou_process::HibouProcessTemporality;
+
+pub fn generate_xlia_model(gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ interaction : &Interaction,
+ temporality : &HibouProcessTemporality) -> String {
+ let mut xlia_model : String = r#"@xlia< system , 1.0 >:"#.to_string();
+ xlia_model.push_str("\n");
+ match temporality {
+ HibouProcessTemporality::Timed => {
+ xlia_model.push_str("timed system <or> HIBOU {\n");
+ },
+ HibouProcessTemporality::UnTimed => {
+ xlia_model.push_str("system <or> HIBOU {\n");
+ }
+ }
+
+ //xlia_model.push_str("@public:\n");
+
+
+ let mut variable_declaration : String = "\t@property:\n".to_string();
+
+ // ***
+ match temporality {
+ HibouProcessTemporality::Timed => {
+ variable_declaration.push_str("\tvar clock last_lf_compare_clock;\n");
+ variable_declaration.push_str("\tvar float trace_delay;\n");
+ },
+ HibouProcessTemporality::UnTimed => {
+ // nothing
+ }
+ }
+
+ // ***
+ let mut trace_compare_actions : Vec<String> = Vec::new();
+ let mut ms_id : usize = 0;
+ for (ms_name,ms_args) in gen_ctx.get_ms_specs() {
+ //let mut signal_string : String = format!("\tsignal {}",ms_name);
+ let mut compare_action_string = format!("\tmachine action_compare_ms_{} {{\n", ms_name);
+ compare_action_string.push_str("\t@moe:\n");
+ compare_action_string.push_str("\t\t@run{\n");
+ match temporality {
+ HibouProcessTemporality::Timed => {
+ compare_action_string.push_str("\t\t\t// time does not flow in this action\n");
+ compare_action_string.push_str( "\t\t\tguard($delay == 0.0);\n" );
+ compare_action_string.push_str("\t\t\t// to compare timed trace delay\n");
+ compare_action_string.push_str( "\t\t\tguard( last_lf_compare_clock == trace_delay );\n" );
+ },
+ HibouProcessTemporality::UnTimed => {
+ // nothing
+ }
+ }
+ compare_action_string.push_str("\t\t\t// values of ms_M_pr_P kept from last symbolic step\n");
+ compare_action_string.push_str("\t\t\t// values of trace_ms_M_pr_P provided by HIBOU\n");
+ let mut arg_count = 0;
+ if ms_args.len() > 0 {
+ for ( arg_type, _) in ms_args {
+ // ***
+ let xlia_arg_type = arg_type.as_xlia_str();
+ let parameter_diversity_name = message_parameter_diversity_name(gen_ctx,ms_id,arg_count);
+ variable_declaration.push_str(&format!("\tvar {} {};\n",xlia_arg_type,parameter_diversity_name));
+ let trace_parameter_diversity_name = trace_message_parameter_diversity_name(gen_ctx,ms_id,arg_count);
+ variable_declaration.push_str(&format!("\tvar {} {};\n",xlia_arg_type,trace_parameter_diversity_name));
+ // ***
+ compare_action_string.push_str( &format!("\t\t\tguard({} == {});\n", parameter_diversity_name, trace_parameter_diversity_name) );
+ // ***
+ /*signal_string.push_str(&arg_type.as_xlia_str());
+ if arg_count < ms_args.len() {
+ signal_string.push_str(",");
+ }*/
+ arg_count = arg_count + 1;
+ }
+ //signal_string.push_str(")");
+ }
+ // ***
+ match temporality {
+ HibouProcessTemporality::Timed => {
+ compare_action_string.push_str("\t\t\t// we now reset the last_lf_compare_clock because we are in the moment of the latest visible action on that lifeline \n");
+ compare_action_string.push_str("\t\t\tlast_lf_compare_clock := 0.0;\n");
+ },
+ HibouProcessTemporality::UnTimed => {
+ // nothing
+ }
+ }
+ // ***
+ compare_action_string.push_str("\t\t}\n");
+ compare_action_string.push_str("\t}\n");
+ trace_compare_actions.push(compare_action_string);
+ //signal_string.push_str(";\n");
+ //xlia_model.push_str(&signal_string);
+ ms_id = ms_id +1;
+ }
+
+ let mut open_scope_action_string = "\tmachine <start> action_open_scopes {\n".to_string();
+ open_scope_action_string.push_str("\t@moe:\n");
+ open_scope_action_string.push_str("\t\t@run{\n");
+ open_scope_action_string.push_str("\t\t\t// creates a new place in each meta-variable vector allowing designation of scoped variables\n");
+ open_scope_action_string.push_str("\t\t\t// called once at the beginning so that every variable vector in the DIVERSITY model has exactly one place for the original instance of the HIBOU meta-variable\n");
+ open_scope_action_string.push_str("\t\t\t// called later every time a scope operator is opened in the execution\n");
+ let vr_names = gen_ctx.get_vr_names();
+ let vr_types = gen_ctx.get_vr_types();
+ for vr_id in 0..vr_names.len() {
+ let vr_index_name = variable_array_index_diversity_name(gen_ctx,vr_id);
+ let vr_vector_name = variable_vector_diversity_name(gen_ctx,vr_id);
+ let vr_base_for_newfresh_name = variable_base_for_newfresh_diversity_name(gen_ctx,vr_id);
+
+ // ***
+ let vr_type_xlia_str : String;
+ if gen_ctx.is_clock( vr_id ) {
+ vr_type_xlia_str = "clock".to_string();
+ } else {
+ let vr_type : &TD_DataType = vr_types.get(vr_id).unwrap();
+ vr_type_xlia_str = vr_type.as_xlia_str();
+ }
+ // ***
+ let vr_base_for_newfresh_xlia_dec = format!("\tvar {} {};\n",vr_type_xlia_str,vr_base_for_newfresh_name);
+ variable_declaration.push_str(&vr_base_for_newfresh_xlia_dec);
+ // ***
+ let var_vector_xlia_dec = format!("\tvar vector<{}> {};\n",vr_type_xlia_str,vr_vector_name);
+ variable_declaration.push_str(&var_vector_xlia_dec);
+ // ***
+ let var_index_dec = format!("\tvar int {};\n", vr_index_name);
+ variable_declaration.push_str(&var_index_dec);
+ // ***
+ open_scope_action_string.push_str( &format!("\t\t\t{} <=< newfresh({});\n", vr_vector_name, vr_base_for_newfresh_name) );
+ }
+ open_scope_action_string.push_str("\t\t}\n");
+ open_scope_action_string.push_str("\t}\n");
+
+ xlia_model.push_str("@composite:");
+ xlia_model.push_str("\n");
+
+ let mut lifelines_actions : HashMap<usize,Vec<String>> = HashMap::new();
+ generate_xlia_lifelines(gen_ctx, exe_ctx, interaction, &mut lifelines_actions, Vec::new());
+
+ for lf_id in 0..gen_ctx.get_lf_num() {
+ let lf_name = gen_ctx.get_lf_name(lf_id).unwrap();
+ let mut lifeline_string : String = format!("\tlifeline machine <or> {} {{\n",lf_name);
+ // ***
+ lifeline_string.push_str("\t@public:\n");
+ lifeline_string.push_str("\t\tport output hevent(string);\n");
+ // ***
+ lifeline_string.push_str(&variable_declaration);
+ lifeline_string.push_str("\t@composite:\n");
+ // ***
+ lifeline_string.push_str( &open_scope_action_string );
+ lifeline_string.push_str( &make_lifeline_initialization_action(gen_ctx,exe_ctx,lf_id) );
+ // ***
+ match lifelines_actions.get(&lf_id) {
+ None => {},
+ Some(lf_actions) => {
+ for lf_act in lf_actions {
+ lifeline_string.push_str(lf_act);
+ }
+ }
+ }
+ // ***
+ for lf_trace_compare_act in &trace_compare_actions {
+ lifeline_string.push_str(lf_trace_compare_act);
+ }
+ // ***
+ lifeline_string.push_str("\t}\n");
+ // ***
+ xlia_model.push_str(&lifeline_string);
+ }
+
+ xlia_model.push_str("@com:\n");
+ xlia_model.push_str("\tconnect<env>{\n");
+ for lf_id in 0..gen_ctx.get_lf_num() {
+ let lf_name = gen_ctx.get_lf_name(lf_id).unwrap();
+ xlia_model.push_str(&format!("\t\toutput {}->hevent;\n",lf_name) );
+ }
+ xlia_model.push_str("\t}\n");
+ xlia_model.push_str("}");
+
+ return xlia_model;
+}
+
+
+fn update_xlia_lifelines_from_lf_act(gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ lf_id : usize,
+ preamble : &Vec<ActionAmbleItem>,
+ postamble : &Vec<ActionAmbleItem>,
+ ms_id : usize,
+ params : &Vec<ValueOrNewFresh>,
+ is_emission : bool,
+ is_target : bool,
+ lifelines_actions : &mut HashMap<usize,Vec<String>>,
+ relative_position : Vec<u32>) {
+
+ // ***
+ let action_name = action_diversity_name(&relative_position);
+ //println!("creating on lifeline {} action on position {}",lf_name,action_name);
+ // ***
+ let mut xlia_action_str : String = format!("\tmachine {} {{\n",action_name);
+ // ***
+ xlia_action_str.push_str("\t@moe:\n");
+ xlia_action_str.push_str("\t\t@run{\n");
+ xlia_action_str.push_str("\t\t// values of index_V provided by HIBOU\n");
+ // ***
+ xlia_action_str.push_str("\t\t\t// Pre-Amble\n");
+ for amble_item in preamble {
+ match amble_item {
+ ActionAmbleItem::Assignment( vr_id, value_or_new_fresh ) => {
+ match value_or_new_fresh {
+ ValueOrNewFresh::NewFresh => {
+ let vr_base_for_newfresh_name = variable_base_for_newfresh_diversity_name(gen_ctx,*vr_id);
+ let vr_complete_name_within_array = variable_diversity_name(gen_ctx,*vr_id);
+ xlia_action_str.push_str( &format!("\t\t\t{} = newfresh({});\n", vr_complete_name_within_array, vr_base_for_newfresh_name) );
+ },
+ ValueOrNewFresh::Value( td_gen ) => {
+ xlia_action_str.push_str( &format!("\t\t\t{} = {};\n",variable_diversity_name(gen_ctx,*vr_id),td_generic_to_xlia(gen_ctx,td_gen)) );
+ }
+ }
+ },
+ ActionAmbleItem::Guard( td_bool ) => {
+ xlia_action_str.push_str( &format!("\t\t\tguard({});\n",td_bool_to_xlia(gen_ctx,td_bool)) );
+ },
+ ActionAmbleItem::Reset( vr_id ) => {
+ let vr_complete_name_within_array = variable_diversity_name(gen_ctx,*vr_id);
+ //xlia_action_str.push_str( &format!("\t\t\treset({});\n", vr_complete_name_within_array) );
+ xlia_action_str.push_str( &format!("\t\t\t{} := 0.0;\n", vr_complete_name_within_array) );
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+ // ***
+ if is_emission {
+ xlia_action_str.push_str("\t\t\t// Emission - values of ms_M_pr_P computed by DIVERSITY - later queried by HIBOU\n");
+ //let mut params_diversity_names : Vec<String> =
+ for idx in 0..params.len() {
+ let parameter_diversity_name = message_parameter_diversity_name(gen_ctx,ms_id,idx);
+ let param_val = params.get(idx).unwrap();
+ match param_val {
+ ValueOrNewFresh::NewFresh => {
+ xlia_action_str.push_str( &format!("\t\t\tnewfresh({});\n", parameter_diversity_name) );
+ },
+ ValueOrNewFresh::Value( td_gen ) => {
+ xlia_action_str.push_str( &format!("\t\t\t{} = {};\n",parameter_diversity_name,td_generic_to_xlia(gen_ctx,td_gen)) );
+ }
+ }
+ }
+ let hevent_str = format!("\"!{}\"", gen_ctx.get_ms_name(ms_id).unwrap());
+ xlia_action_str.push_str( &format!("\t\t\toutput hevent ({});\n", hevent_str ) );
+ } else {
+ xlia_action_str.push_str("\t\t\t// Reception - values of ms_M_pr_P provided by HIBOU -\n");
+ for idx in 0..params.len() {
+ let parameter_diversity_name = message_parameter_diversity_name(gen_ctx,ms_id,idx);
+ let param_val = params.get(idx).unwrap();
+ match param_val {
+ ValueOrNewFresh::NewFresh => {
+ if is_target {
+ // do nothing
+ } else {
+ xlia_action_str.push_str("\t\t\t// newfresh from the environment in a reception that isn't a target of an emission modelled in the DS\n");
+ xlia_action_str.push_str( &format!("\t\t\tnewfresh({});\n", parameter_diversity_name) );
+ }
+ },
+ ValueOrNewFresh::Value( td_gen ) => {
+ // do nothing
+ }
+ }
+ }
+ let hevent_str = format!("\"?{}\"", gen_ctx.get_ms_name(ms_id).unwrap());
+ xlia_action_str.push_str( &format!("\t\t\toutput hevent ({});\n", hevent_str ) );
+ }
+ // ***
+ xlia_action_str.push_str("\t\t\t// Post-Amble\n");
+ for amble_item in postamble {
+ match amble_item {
+ ActionAmbleItem::Assignment( vr_id, value_or_new_fresh ) => {
+ match value_or_new_fresh {
+ ValueOrNewFresh::NewFresh => {
+ let vr_base_for_newfresh_name = variable_base_for_newfresh_diversity_name(gen_ctx,*vr_id);
+ let vr_complete_name_within_array = variable_diversity_name(gen_ctx,*vr_id);
+ xlia_action_str.push_str( &format!("\t\t\t{} = newfresh({});\n", vr_complete_name_within_array, vr_base_for_newfresh_name) );
+ },
+ ValueOrNewFresh::Value( td_gen ) => {
+ xlia_action_str.push_str( &format!("\t\t\t{} = {};\n",variable_diversity_name(gen_ctx,*vr_id),td_generic_to_xlia(gen_ctx,td_gen)) );
+ }
+ }
+ },
+ ActionAmbleItem::Guard( td_bool ) => {
+ xlia_action_str.push_str( &format!("\t\t\tguard({});\n",td_bool_to_xlia(gen_ctx,td_bool)) );
+ },
+ ActionAmbleItem::Reset( vr_id ) => {
+ let vr_complete_name_within_array = variable_diversity_name(gen_ctx,*vr_id);
+ xlia_action_str.push_str( &format!("\t\t\treset({});\n", vr_complete_name_within_array) );
+ },
+ _ => {
+ panic!();
+ }
+ }
+ }
+ // ***
+ xlia_action_str.push_str("\t\t}\n");
+ xlia_action_str.push_str("\t}\n");
+ // ***
+ match lifelines_actions.get(&lf_id) {
+ None => {
+ lifelines_actions.insert(lf_id,vec![xlia_action_str] );
+ },
+ Some( action_strings_vec ) => {
+ let mut act_str_vec = action_strings_vec.clone();
+ act_str_vec.push( xlia_action_str );
+ lifelines_actions.insert(lf_id, act_str_vec );
+ }
+ }
+}
+
+fn generate_xlia_lifelines(gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ interaction : &Interaction,
+ lifelines_actions : &mut HashMap<usize,Vec<String>>,
+ relative_position : Vec<u32>) {
+ match interaction {
+ Interaction::Empty => {},
+ Interaction::Action( obs_act ) => {
+ match &obs_act.act_kind {
+ ObservableActionKind::Emission( targets ) => {
+ update_xlia_lifelines_from_lf_act(gen_ctx,exe_ctx,obs_act.lf_act.lf_id,
+ &obs_act.lf_act.preamble,&obs_act.lf_act.postamble,obs_act.ms_id,&obs_act.params,true,false,
+ lifelines_actions,relative_position.clone());
+ // ***
+ let mut target_counter : u32 = 1;
+ for target in targets {
+ let mut rel_pos = relative_position.clone();
+ rel_pos.push(target_counter );
+ target_counter = target_counter +1;
+ update_xlia_lifelines_from_lf_act(gen_ctx,exe_ctx,target.lf_id,
+ &target.preamble,&target.postamble,obs_act.ms_id,&obs_act.params,false,true,
+ lifelines_actions,rel_pos);
+ }
+ },
+ ObservableActionKind::Reception => {
+ update_xlia_lifelines_from_lf_act(gen_ctx,exe_ctx,obs_act.lf_act.lf_id,
+ &obs_act.lf_act.preamble,&obs_act.lf_act.postamble,obs_act.ms_id,&obs_act.params,false,false,
+ lifelines_actions,relative_position.clone());
+ }
+ }
+ },
+ Interaction::Scope(_,sub_interaction) => {
+ let mut rel_pos = relative_position.clone();
+ rel_pos.push(1 );
+ generate_xlia_lifelines(gen_ctx,exe_ctx,sub_interaction,lifelines_actions,rel_pos);
+ },
+ Interaction::Loop(_,sub_interaction) => {
+ let mut rel_pos = relative_position.clone();
+ rel_pos.push(1 );
+ generate_xlia_lifelines(gen_ctx,exe_ctx,sub_interaction,lifelines_actions,rel_pos);
+ },
+ Interaction::Strict(subint1,subint2) => {
+ {
+ let mut rel_pos = relative_position.clone();
+ rel_pos.push(1 );
+ generate_xlia_lifelines(gen_ctx,exe_ctx,subint1,lifelines_actions,rel_pos);
+ }
+ {
+ let mut rel_pos = relative_position.clone();
+ rel_pos.push(2 );
+ generate_xlia_lifelines(gen_ctx,exe_ctx,subint2,lifelines_actions,rel_pos);
+ }
+ },
+ Interaction::Seq(subint1,subint2) => {
+ {
+ let mut rel_pos = relative_position.clone();
+ rel_pos.push(1 );
+ generate_xlia_lifelines(gen_ctx,exe_ctx,subint1,lifelines_actions,rel_pos);
+ }
+ {
+ let mut rel_pos = relative_position.clone();
+ rel_pos.push(2 );
+ generate_xlia_lifelines(gen_ctx,exe_ctx,subint2,lifelines_actions,rel_pos);
+ }
+ },
+ Interaction::Alt(subint1,subint2) => {
+ {
+ let mut rel_pos = relative_position.clone();
+ rel_pos.push(1 );
+ generate_xlia_lifelines(gen_ctx,exe_ctx,subint1,lifelines_actions,rel_pos);
+ }
+ {
+ let mut rel_pos = relative_position.clone();
+ rel_pos.push(2 );
+ generate_xlia_lifelines(gen_ctx,exe_ctx,subint2,lifelines_actions,rel_pos);
+ }
+ },
+ Interaction::Par(subint1,subint2) => {
+ {
+ let mut rel_pos = relative_position.clone();
+ rel_pos.push(1 );
+ generate_xlia_lifelines(gen_ctx,exe_ctx,subint1,lifelines_actions,rel_pos);
+ }
+ {
+ let mut rel_pos = relative_position.clone();
+ rel_pos.push(2 );
+ generate_xlia_lifelines(gen_ctx,exe_ctx,subint2,lifelines_actions,rel_pos);
+ }
+ }
+ }
+}
diff --git a/src/xlia/model_initialization.rs b/src/xlia/model_initialization.rs
new file mode 100644
index 0000000..4559349
--- /dev/null
+++ b/src/xlia/model_initialization.rs
@@ -0,0 +1,113 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashMap;
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::interaction::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::td_type::TD_DataType;
+use crate::core::syntax::data::builtin::float::TD_Float;
+use crate::core::syntax::data::builtin::integer::TD_Integer;
+use crate::core::syntax::data::builtin::string::TD_String;
+use crate::core::syntax::data::builtin::bool::TD_Bool;
+use crate::core::syntax::data::var_ref::VariableReference;
+
+use crate::tools::fold_vec_to_string;
+
+use crate::xlia::xlia_build_name_tools::*;
+use crate::xlia::data::{td_generic_to_xlia,td_bool_to_xlia};
+
+use crate::process::hibou_process::HibouProcessTemporality;
+
+
+pub fn make_lifeline_initialization_action(gen_ctx : &GeneralContext,
+ exe_ctx : &ExecutionContext,
+ lf_id : usize) -> String {
+ let mut xlia_action_str : String = "\tmachine initialization {\n".to_string();
+ // ***
+ xlia_action_str.push_str("\t@moe:\n");
+ xlia_action_str.push_str("\t\t@run{\n");
+ xlia_action_str.push_str("\t\t// initialization of variables according to @init section of .hsf Hibou Specification File\n");
+ // ***
+ match exe_ctx.get_lf_interpretation(lf_id) {
+ None => {},
+ Some( interpretation ) => {
+ for (vr_id,td_gen) in interpretation.iter() {
+ xlia_action_str.push_str( &generate_xlia_vr_initialization(gen_ctx,exe_ctx,*vr_id,td_gen) );
+ }
+ }
+ }
+ // ***
+ xlia_action_str.push_str("\t\t}\n");
+ xlia_action_str.push_str("\t}\n");
+ return xlia_action_str;
+}
+
+
+fn generate_xlia_vr_initialization(gen_ctx:&GeneralContext, exe_ctx:&ExecutionContext, vr_id : usize, td_gen: &TD_Generic) -> String {
+ let variable_diversity_name = variable_diversity_name(gen_ctx,vr_id);
+ match td_gen {
+ TD_Generic::String(td_str) => {
+ match td_str {
+ TD_String::Reference(_) => {
+ let vr_base_for_newfresh_name = variable_base_for_newfresh_diversity_name(gen_ctx,vr_id);
+ return format!("\t\t\t{} = newfresh({});\n", variable_diversity_name, vr_base_for_newfresh_name);
+ },
+ _ => {
+ return format!("\t\t\t{} = {};\n",variable_diversity_name,td_generic_to_xlia(gen_ctx,td_gen));
+ }/*
+ TD_String::Value( raw_str ) => {
+ let value = format!("\"{}\"",raw_str);
+ return format!("\t\t\t{} = {};\n", variable_diversity_name, value) );
+ },*/
+ }
+ },
+ TD_Generic::Bool(td_bool) => {
+ match td_bool {
+ TD_Bool::Reference(_) => {
+ let vr_base_for_newfresh_name = variable_base_for_newfresh_diversity_name(gen_ctx,vr_id);
+ return format!("\t\t\t{} = newfresh({});\n", variable_diversity_name, vr_base_for_newfresh_name);
+ },
+ _ => {
+ return format!("\t\t\t{} = {};\n",variable_diversity_name,td_generic_to_xlia(gen_ctx,td_gen));
+ }
+ }
+ },
+ TD_Generic::Integer(td_int) => {
+ match td_int {
+ TD_Integer::Reference(_) => {
+ let vr_base_for_newfresh_name = variable_base_for_newfresh_diversity_name(gen_ctx,vr_id);
+ return format!("\t\t\t{} = newfresh({});\n", variable_diversity_name, vr_base_for_newfresh_name);
+ },
+ _ => {
+ return format!("\t\t\t{} = {};\n",variable_diversity_name,td_generic_to_xlia(gen_ctx,td_gen));
+ }
+ }
+ },
+ TD_Generic::Float(td_float) => {
+ match td_float {
+ TD_Float::Reference(_) => {
+ let vr_base_for_newfresh_name = variable_base_for_newfresh_diversity_name(gen_ctx,vr_id);
+ return format!("\t\t\t{} = newfresh({});\n", variable_diversity_name, vr_base_for_newfresh_name);
+ },
+ _ => {
+ return format!("\t\t\t{} = {};\n",variable_diversity_name,td_generic_to_xlia(gen_ctx,td_gen));
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/xlia/xlia_build_name_tools.rs b/src/xlia/xlia_build_name_tools.rs
new file mode 100644
index 0000000..f76be20
--- /dev/null
+++ b/src/xlia/xlia_build_name_tools.rs
@@ -0,0 +1,59 @@
+/*******************************************************************************
+* Copyright (c) 2021 CentraleSupelec, CEA-LIST
+*
+* This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License 2.0
+* which accompanies this distribution, and is available at
+* https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*
+* Contributors:
+* Erwan Mahé (CentraleSupelec) - initial API and implementation
+*******************************************************************************/
+
+use std::collections::HashMap;
+use crate::core::context::general::GeneralContext;
+use crate::core::context::execution::ExecutionContext;
+use crate::core::syntax::interaction::*;
+use crate::core::syntax::action::*;
+use crate::core::syntax::data::generic::TD_Generic;
+use crate::core::syntax::data::td_type::TD_DataType;
+
+use crate::tools::fold_vec_to_string;
+
+pub fn action_diversity_name(relative_position : &Vec<u32>) -> String {
+ return format!("action_{}",fold_vec_to_string(relative_position));
+}
+
+pub fn message_parameter_diversity_name(gen_ctx : &GeneralContext, ms_id : usize, pr_id : usize) -> String {
+ let ms_name= gen_ctx.get_ms_name(ms_id).unwrap();
+ return format!("ms_{}_pr_{}",ms_name,pr_id);
+}
+
+pub fn trace_message_parameter_diversity_name(gen_ctx : &GeneralContext, ms_id : usize, pr_id : usize) -> String {
+ let ms_name= gen_ctx.get_ms_name(ms_id).unwrap();
+ return format!("trace_ms_{}_pr_{}",ms_name,pr_id);
+}
+
+pub fn variable_array_index_diversity_name(gen_ctx : &GeneralContext, vr_id : usize) -> String {
+ let vr_name : String = gen_ctx.get_vr_name(vr_id).unwrap();
+ return format!("index_{}",vr_name);
+}
+
+pub fn variable_diversity_name(gen_ctx : &GeneralContext, vr_id : usize) -> String {
+ let vr_name : String = gen_ctx.get_vr_name(vr_id).unwrap();
+ let index_name = variable_array_index_diversity_name(gen_ctx,vr_id);
+ return format!("lf_var_{}[{}]",vr_name,index_name);
+}
+
+pub fn variable_vector_diversity_name(gen_ctx : &GeneralContext, vr_id : usize) -> String {
+ let vr_name : String = gen_ctx.get_vr_name(vr_id).unwrap();
+ return format!("lf_var_{}",vr_name);
+}
+
+pub fn variable_base_for_newfresh_diversity_name(gen_ctx : &GeneralContext, vr_id : usize) -> String {
+ let vr_name : String = gen_ctx.get_vr_name(vr_id).unwrap();
+ return format!("var_{}",vr_name);
+}
+
diff --git a/test.tmp b/test.tmp
deleted file mode 100644
index 558ddcb..0000000
--- a/test.tmp
+++ /dev/null
@@ -1,3 +0,0 @@
-test4 --> 42
-sethsdgh
-