blob: 11d8e7e20e555d30fc3da9a4a3f3950ba27721e4 [file] [log] [blame]
/*******************************************************************************
* 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);
}
}
}
}