diff --git a/m_ext/0/cibles.m b/m_ext/0/cibles.m index 819810d27..e3ac2cf0f 100644 --- a/m_ext/0/cibles.m +++ b/m_ext/0/cibles.m @@ -59,6 +59,11 @@ BOBO4 : calculee base primrest = 0 restituee : "" ; BOBORES : calculee base primrest = 0 restituee : "" ; +CONST0 : const = 0; +CONST1 : const = 1; +CONST2 : const = 2; +CONST3 : const = 3; + espace_variables ESP : categorie saisie, base; cible test_dans_domaine: @@ -626,6 +631,24 @@ afficher_erreur nom(VAR) ": " par_defaut: afficher "Y = ?, echec\n"; ) +aiguillage (Y) : ( + cas CONST0: + afficher "Y = CONST0, echec\n"; + cas CONST1: + afficher "Y = CONST1, OK!\n"; + cas indefini: + afficher "Y = --indefini--, echec\n"; + par_defaut: + afficher "Y = ?, echec\n"; +) +aiguillage nom (Y) : ( + cas X: + afficher "X = Y, ah bon?\n"; + cas Y: + afficher "Y = Y, ouf\n"; + par_defaut: + afficher "Y = ?, echec\n"; +) afficher "FIN test aiguillage\n"; # Test stop fonction diff --git a/m_ext/2022/correctif.m b/m_ext/2022/correctif.m index 2d14c024c..d796c8605 100644 --- a/m_ext/2022/correctif.m +++ b/m_ext/2022/correctif.m @@ -829,13 +829,11 @@ si present(VAR) et VAR >= 0 alors application: iliad; arguments: ATTR; resultat: NAT; -si ATTR = 0 alors - NAT = N_REVENU; -sinon_si ATTR = 1 alors - NAT = N_CHARGE; -sinon - NAT = N_INDEFINIE; -finsi +aiguillage(ATTR):( + cas 0: NAT = N_REVENU; + cas 1: NAT = N_CHARGE; + par_defaut: NAT = N_INDEFINIE; +) cible get_nature: application: iliad; @@ -861,19 +859,14 @@ sinon_si dans_domaine(VAR, calculee *) alors NATURE = N_INDEFINIE; finsi sinon_si dans_domaine(VAR, saisie contexte) alors - si meme_variable(VAR, V_REGCO) alors - NATURE = N_REVENU; - sinon_si - meme_variable(VAR, V_EAG) - ou meme_variable(VAR, V_EAD) - ou meme_variable(VAR, V_CNR) - ou meme_variable(VAR, V_CNR2) - ou meme_variable(VAR, V_CR2) - alors - NATURE = N_CHARGE; - sinon - NATURE = N_REVENU; - finsi + aiguillage nom (VAR): ( + cas V_REGCO: NATURE = N_REVENU; + cas V_EAG: + cas V_CNR: + cas V_CNR2: + cas V_CR2: NATURE = N_CHARGE; + par_defaut: NATURE = N_REVENU; + ) sinon_si dans_domaine(VAR, saisie variation) ou dans_domaine(VAR, saisie penalite) @@ -2209,17 +2202,25 @@ si meme_variable(champ_evenement(R, code), REGCO) alors application: iliad; arguments: PENA; resultat: TAUX; -si PENA dans (2, 7, 10, 17) alors - TAUX = 10; -sinon_si PENA dans (3, 8, 11, 30, 55) alors - TAUX = 40; -sinon_si PENA dans (4, 5, 9, 12, 31, 32) alors - TAUX = 80; -sinon_si PENA = 6 alors - TAUX = 100; -sinon - TAUX = 0; -finsi +aiguillage(PENA) : ( + cas 2: + cas 7: + cas 10: + cas 17: TAUX = 10; + cas 3: + cas 8: + cas 11: + cas 30: + cas 55: TAUX = 40; + cas 4: + cas 5: + cas 9: + cas 12: + cas 31: + cas 32: TAUX = 80; + cas 6: TAUX = 100; + par_defaut: TAUX = 0; +) fonction is_minoration_sf: application: iliad; @@ -2304,23 +2305,19 @@ sinon_si PENA dans (4, 5, 9, 12, 31, 32) alors cible get_code_situation_famille: application: iliad; arguments: RESULTAT, CORR, VAR; -si meme_variable(VAR, 0AM) alors - RESULTAT = SF_MARIAGE; -sinon_si meme_variable(VAR, 0AC) alors - RESULTAT = SF_CELIBAT; -sinon_si meme_variable(VAR, 0AD) alors - RESULTAT = SF_DIVORCE; -sinon_si meme_variable(VAR, 0AO) alors - RESULTAT = SF_PACSE; -sinon_si meme_variable(VAR, 0AV) alors - si positif(CORR) et GLOBAL.ANNEE_DECES_CONJOINT = GLOBAL.ANNEE_REVENU alors - RESULTAT = SF_VEUVAGE_TRUE; - sinon - RESULTAT = SF_VEUVAGE_FALSE; - finsi -sinon - RESULTAT = SF_INVALIDE; -finsi +aiguillage nom (VAR):( + cas 0AM: RESULTAT = SF_MARIAGE; + cas 0AC: RESULTAT = SF_CELIBAT; + cas 0AD: RESULTAT = SF_DIVORCE; + cas 0AO: RESULTAT = SF_PACSE; + cas 0AV: + si positif(CORR) et GLOBAL.ANNEE_DECES_CONJOINT = GLOBAL.ANNEE_REVENU alors + RESULTAT = SF_VEUVAGE_TRUE; + sinon + RESULTAT = SF_VEUVAGE_FALSE; + finsi + par_defaut: RESULTAT = SF_INVALIDE; +) cible is_rappel_strate: application: iliad; @@ -2611,131 +2608,132 @@ ou meme_variable(VAR, 0DB) application: iliad; arguments: RESULTAT, R, MAJ; variables_temporaires: EST_SF_NAISS, EST_TAX_INIT; -si MAJ = MAJ_TL alors - RESULTAT = (attribut(champ_evenement(R, code), categorie_TL) != 10); -sinon_si MAJ = MAJ_NON_TL alors - RESULTAT = (attribut(champ_evenement(R, code), categorie_TL) = 10); -sinon_si MAJ = MAJ_TL15 alors - RESULTAT = (attribut(champ_evenement(R, code), categorie_TL) != 15); -sinon_si MAJ = MAJ_NON_TL15 alors - RESULTAT = (attribut(champ_evenement(R, code), categorie_TL) = 15); -sinon_si MAJ = MAJ_RAPPEL_C alors - RESULTAT = ( - champ_evenement(R, sens) = SENS_C - et (champ_evenement(R, penalite) < 1 ou champ_evenement(R, penalite) = 99) - et GLOBAL.CODE_PENA != 22 - ); -sinon_si MAJ = MAJ_RAPPEL_CP alors - RESULTAT = ( - champ_evenement(R, sens) = SENS_C - et champ_evenement(R, penalite) > 1 - ); -sinon_si MAJ = MAJ_RAPPEL_CP01 alors - RESULTAT = ( - champ_evenement(R, sens) = SENS_C - et champ_evenement(R, penalite) = 1 - ); -sinon_si MAJ = MAJ_RAPPEL_CP22 alors - RESULTAT = ( - champ_evenement(R, sens) = SENS_C - et champ_evenement(R, penalite) = 22 - ); -sinon_si MAJ = MAJ_RAPPEL_CP24 alors - RESULTAT = ( - champ_evenement(R, sens) = SENS_C - et champ_evenement(R, penalite) = 24 - ); -sinon_si MAJ = MAJ_RAPPEL_F alors - calculer cible est_code_sf_naiss : avec EST_SF_NAISS, champ_evenement(R, code); - RESULTAT = ( - champ_evenement(R, sens) = SENS_R - et champ_evenement(R, penalite) = 1 - et positif(EST_SF_NAISS) - ); -sinon_si MAJ = MAJ_RAPPEL_NF alors - calculer cible est_code_sf_naiss : avec EST_SF_NAISS, champ_evenement(R, code); - RESULTAT = ( - champ_evenement(R, sens) = SENS_R - et champ_evenement(R, penalite) = 1 - et (non positif(EST_SF_NAISS)) - ); -sinon_si MAJ = MAJ_RAPPEL_M alors - calculer cible est_code_sf_naiss : avec EST_SF_NAISS, champ_evenement(R, code); - RESULTAT = ( - champ_evenement(R, sens) = SENS_M - et (non positif(EST_SF_NAISS)) - et non ( - meme_variable(champ_evenement(R, code), REGCO) - et (GLOBAL.PENALITE_REGCO dans (1, 22, 24, 99)) - ) - ); -sinon_si MAJ = MAJ_RAPPEL_MF alors - calculer cible est_code_sf_naiss : avec EST_SF_NAISS, champ_evenement(R, code); - RESULTAT = (champ_evenement(R, sens) = SENS_M et positif(EST_SF_NAISS)); -sinon_si MAJ = MAJ_RAPPEL_NON_M alors - RESULTAT = (champ_evenement(R, sens) != SENS_M); -sinon_si MAJ = MAJ_RAPPEL_P alors - RESULTAT = (champ_evenement(R, sens) = SENS_P); -sinon_si MAJ = MAJ_RAPPEL_R alors - RESULTAT = (champ_evenement(R, sens) = SENS_R); -sinon_si MAJ = MAJ_RAPPEL_R55 alors - RESULTAT = ( - meme_variable(champ_evenement(R, code), REGCO) - et (GLOBAL.PENALITE_REGCO dans (1, 99)) - ); -sinon_si MAJ = MAJ_1728 alors - RESULTAT = (champ_evenement(R, penalite) dans (7, 8, 10, 11, 17, 18, 31)); -sinon_si MAJ = MAJ_ABAT_20 alors - calculer cible is_rappel_abat_20_proc : avec RESULTAT, R; -sinon_si MAJ = MAJ_CODE_1729_2A5 alors - RESULTAT = (champ_evenement(R, penalite) dans (2, 3, 4, 5, 30, 32, 35, 55)); -sinon_si MAJ = MAJ_CODE_1729_6 alors - RESULTAT = (champ_evenement(R, penalite) = 6); -sinon_si MAJ = MAJ_CODE_22 alors - RESULTAT = ( - champ_evenement(R, penalite) = 22 - et ( +aiguillage (MAJ):( + cas MAJ_TL: + RESULTAT = (attribut(champ_evenement(R, code), categorie_TL) != 10); + cas MAJ_NON_TL: + RESULTAT = (attribut(champ_evenement(R, code), categorie_TL) = 10); + cas MAJ_TL15: + RESULTAT = (attribut(champ_evenement(R, code), categorie_TL) != 15); + cas MAJ_NON_TL15 : + RESULTAT = (attribut(champ_evenement(R, code), categorie_TL) = 15); + cas MAJ_RAPPEL_C : + RESULTAT = ( + champ_evenement(R, sens) = SENS_C + et (champ_evenement(R, penalite) < 1 ou champ_evenement(R, penalite) = 99) + et GLOBAL.CODE_PENA != 22 + ); + cas MAJ_RAPPEL_CP : + RESULTAT = ( + champ_evenement(R, sens) = SENS_C + et champ_evenement(R, penalite) > 1 + ); + cas MAJ_RAPPEL_CP01 : + RESULTAT = ( + champ_evenement(R, sens) = SENS_C + et champ_evenement(R, penalite) = 1 + ); + cas MAJ_RAPPEL_CP22 : + RESULTAT = ( + champ_evenement(R, sens) = SENS_C + et champ_evenement(R, penalite) = 22 + ); + cas MAJ_RAPPEL_CP24 : + RESULTAT = ( + champ_evenement(R, sens) = SENS_C + et champ_evenement(R, penalite) = 24 + ); + cas MAJ_RAPPEL_F : + calculer cible est_code_sf_naiss : avec EST_SF_NAISS, champ_evenement(R, code); + RESULTAT = ( champ_evenement(R, sens) = SENS_R - ou meme_variable(champ_evenement(R, code), REGCO) - ) - ); -sinon_si MAJ = MAJ_CODE_24 alors - RESULTAT = ( - champ_evenement(R, penalite) = 24 - et ( + et champ_evenement(R, penalite) = 1 + et positif(EST_SF_NAISS) + ); + cas MAJ_RAPPEL_NF : + calculer cible est_code_sf_naiss : avec EST_SF_NAISS, champ_evenement(R, code); + RESULTAT = ( champ_evenement(R, sens) = SENS_R - ou meme_variable(champ_evenement(R, code), REGCO) - ) - ); -sinon_si MAJ = MAJ_CONTEXTE_22 alors - calculer cible est_code_tax_init : avec EST_TAX_INIT, champ_evenement(R, code); - RESULTAT = (GLOBAL.CODE_PENA = 22 et positif(EST_TAX_INIT)); -sinon_si MAJ = MAJ_MENTION_EXP_99 alors - calculer cible est_code_tax_init : avec EST_TAX_INIT, champ_evenement(R, code); - RESULTAT = ( - champ_evenement(R, penalite) = 99 - et (non positif(GLOBAL.DEFAUT)) - et non ( - meme_variable(champ_evenement(R, code), REGCO) - ou positif(EST_TAX_INIT) - ) - ); -sinon_si MAJ = MAJ_MENTION_EXP_99R alors - calculer cible est_code_tax_init : avec EST_TAX_INIT, champ_evenement(R, code); - RESULTAT = ( - champ_evenement(R, penalite) = 99 - et GLOBAL.CODE_PENA != 22 - et (non positif(GLOBAL.DEFAUT)) - et ( + et champ_evenement(R, penalite) = 1 + et (non positif(EST_SF_NAISS)) + ); + cas MAJ_RAPPEL_M : + calculer cible est_code_sf_naiss : avec EST_SF_NAISS, champ_evenement(R, code); + RESULTAT = ( + champ_evenement(R, sens) = SENS_M + et (non positif(EST_SF_NAISS)) + et non ( + meme_variable(champ_evenement(R, code), REGCO) + et (GLOBAL.PENALITE_REGCO dans (1, 22, 24, 99)) + ) + ); + cas MAJ_RAPPEL_MF : + calculer cible est_code_sf_naiss : avec EST_SF_NAISS, champ_evenement(R, code); + RESULTAT = (champ_evenement(R, sens) = SENS_M et positif(EST_SF_NAISS)); + cas MAJ_RAPPEL_NON_M : + RESULTAT = (champ_evenement(R, sens) != SENS_M); + cas MAJ_RAPPEL_P : + RESULTAT = (champ_evenement(R, sens) = SENS_P); + cas MAJ_RAPPEL_R : + RESULTAT = (champ_evenement(R, sens) = SENS_R); + cas MAJ_RAPPEL_R55 : + RESULTAT = ( meme_variable(champ_evenement(R, code), REGCO) - ou positif(EST_TAX_INIT) - ) - ); -sinon_si MAJ = MAJ_NON_MENTION_EXP alors - RESULTAT = 1; -sinon - RESULTAT = 0; -finsi + et (GLOBAL.PENALITE_REGCO dans (1, 99)) + ); + cas MAJ_1728 : + RESULTAT = (champ_evenement(R, penalite) dans (7, 8, 10, 11, 17, 18, 31)); + cas MAJ_ABAT_20 : + calculer cible is_rappel_abat_20_proc : avec RESULTAT, R; + cas MAJ_CODE_1729_2A5 : + RESULTAT = (champ_evenement(R, penalite) dans (2, 3, 4, 5, 30, 32, 35, 55)); + cas MAJ_CODE_1729_6 : + RESULTAT = (champ_evenement(R, penalite) = 6); + cas MAJ_CODE_22 : + RESULTAT = ( + champ_evenement(R, penalite) = 22 + et ( + champ_evenement(R, sens) = SENS_R + ou meme_variable(champ_evenement(R, code), REGCO) + ) + ); + cas MAJ_CODE_24 : + RESULTAT = ( + champ_evenement(R, penalite) = 24 + et ( + champ_evenement(R, sens) = SENS_R + ou meme_variable(champ_evenement(R, code), REGCO) + ) + ); + cas MAJ_CONTEXTE_22 : + calculer cible est_code_tax_init : avec EST_TAX_INIT, champ_evenement(R, code); + RESULTAT = (GLOBAL.CODE_PENA = 22 et positif(EST_TAX_INIT)); + cas MAJ_MENTION_EXP_99 : + calculer cible est_code_tax_init : avec EST_TAX_INIT, champ_evenement(R, code); + RESULTAT = ( + champ_evenement(R, penalite) = 99 + et (non positif(GLOBAL.DEFAUT)) + et non ( + meme_variable(champ_evenement(R, code), REGCO) + ou positif(EST_TAX_INIT) + ) + ); + cas MAJ_MENTION_EXP_99R : + calculer cible est_code_tax_init : avec EST_TAX_INIT, champ_evenement(R, code); + RESULTAT = ( + champ_evenement(R, penalite) = 99 + et GLOBAL.CODE_PENA != 22 + et (non positif(GLOBAL.DEFAUT)) + et ( + meme_variable(champ_evenement(R, code), REGCO) + ou positif(EST_TAX_INIT) + ) + ); + cas MAJ_NON_MENTION_EXP : + RESULTAT = 1; + par_defaut : + RESULTAT = 0; +) cible is_rappel_autorise: application: iliad; @@ -5513,23 +5511,19 @@ sinon_si positif(champ_evenement(R, 2042_rect)) et C1 > R1 alors cible is_code_situation_famille: application: iliad; arguments: RES_SF, VAR; -si meme_variable(VAR, 0AM) alors - RES_SF = SF_MARIAGE; -sinon_si meme_variable(VAR, 0AC) alors - RES_SF = SF_CELIBAT; -sinon_si meme_variable(VAR, 0AD) alors - RES_SF = SF_DIVORCE; -sinon_si meme_variable(VAR, 0AO) alors - RES_SF = SF_PACSE; -sinon_si meme_variable(VAR, 0AV) alors - si GLOBAL.ANNEE_DECES_CONJOINT = GLOBAL.ANNEE_REVENU alors - RES_SF = SF_VEUVAGE_TRUE; - sinon - RES_SF = SF_VEUVAGE_FALSE; - finsi -sinon - RES_SF = SF_INVALIDE; -finsi +aiguillage nom (VAR) : ( + cas 0AM: RES_SF = SF_MARIAGE; + cas 0AC: RES_SF = SF_CELIBAT; + cas 0AD: RES_SF = SF_DIVORCE; + cas 0AO: RES_SF = SF_PACSE; + cas 0AV: + si GLOBAL.ANNEE_DECES_CONJOINT = GLOBAL.ANNEE_REVENU alors + RES_SF = SF_VEUVAGE_TRUE; + sinon + RES_SF = SF_VEUVAGE_FALSE; + finsi + par_defaut: RES_SF = SF_INVALIDE; +) cible is_code_situation_famille_r: application: iliad; @@ -6583,41 +6577,40 @@ si non present(GLOBAL.CMAJ) alors : variable R : entre 0..(nb_evenements() - 1) increment 1 : dans ( - si meme_variable(champ_evenement(R, code), 8VV) alors - GLOBAL.PRESENT_8VV = 1; - sinon_si meme_variable(champ_evenement(R, code), 8VW) alors - GLOBAL.PRESENT_8VW = 1; - sinon_si meme_variable(champ_evenement(R, code), 9YT) alors - GLOBAL.PRESENT_9YT = 1; - si champ_evenement(R, montant) = 18 alors - GLOBAL.MONTANT_9YT = 7; - sinon - GLOBAL.MONTANT_9YT = champ_evenement(R, montant); - finsi - GLOBAL.PENALITE_9YT = champ_evenement(R, penalite); - GLOBAL.NUM_EVT_9YT = champ_evenement(R, numero); - CORR.CMAJ2 = champ_evenement(R, montant); - GLOBAL.CMAJ2 = champ_evenement(R, montant); - si GLOBAL.MONTANT_9YT != 0 alors - GLOBAL.SENS_9YT = champ_evenement(R, sens); - GLOBAL.IND_20_9YT = champ_evenement(R, 2042_rect); - GLOBAL.BASE_TL_9YT = champ_evenement(R, base_tl); - GLOBAL.R_TARDIF = 1; - finsi - sinon_si meme_variable(champ_evenement(R, code), 9YU) alors - GLOBAL.PRESENT_9YU = 1; - GLOBAL.MONTANT_9YU = champ_evenement(R, montant); - GLOBAL.PENALITE_9YU = champ_evenement(R, penalite); - GLOBAL.NUM_EVT_9YU = champ_evenement(R, numero); - GLOBAL.SENS_9YU = champ_evenement(R, sens); - MOIS = vers_mois(champ_evenement(R, montant)); - ANNEE = vers_annee(champ_evenement(R, montant)); - CORR.DATEINR = ANNEE * 10000 + MOIS * 100 + 1; - GLOBAL.DATEINR = CORR.DATEINR; - CORR.MOISAN2 = champ_evenement(R, montant); - GLOBAL.MOISAN2 = champ_evenement(R, montant); - GLOBAL.DATE_9YU = vers_date(MOIS, ANNEE); - finsi + aiguillage nom (champ_evenement(R, code)) : ( + cas 8VV: GLOBAL.PRESENT_8VV = 1; + cas 8VW: GLOBAL.PRESENT_8VW = 1; + cas 9YT: + GLOBAL.PRESENT_9YT = 1; + si champ_evenement(R, montant) = 18 alors + GLOBAL.MONTANT_9YT = 7; + sinon + GLOBAL.MONTANT_9YT = champ_evenement(R, montant); + finsi + GLOBAL.PENALITE_9YT = champ_evenement(R, penalite); + GLOBAL.NUM_EVT_9YT = champ_evenement(R, numero); + CORR.CMAJ2 = champ_evenement(R, montant); + GLOBAL.CMAJ2 = champ_evenement(R, montant); + si GLOBAL.MONTANT_9YT != 0 alors + GLOBAL.SENS_9YT = champ_evenement(R, sens); + GLOBAL.IND_20_9YT = champ_evenement(R, 2042_rect); + GLOBAL.BASE_TL_9YT = champ_evenement(R, base_tl); + GLOBAL.R_TARDIF = 1; + finsi + cas 9YU: + GLOBAL.PRESENT_9YU = 1; + GLOBAL.MONTANT_9YU = champ_evenement(R, montant); + GLOBAL.PENALITE_9YU = champ_evenement(R, penalite); + GLOBAL.NUM_EVT_9YU = champ_evenement(R, numero); + GLOBAL.SENS_9YU = champ_evenement(R, sens); + MOIS = vers_mois(champ_evenement(R, montant)); + ANNEE = vers_annee(champ_evenement(R, montant)); + CORR.DATEINR = ANNEE * 10000 + MOIS * 100 + 1; + GLOBAL.DATEINR = CORR.DATEINR; + CORR.MOISAN2 = champ_evenement(R, montant); + GLOBAL.MOISAN2 = champ_evenement(R, montant); + GLOBAL.DATE_9YU = vers_date(MOIS, ANNEE); + ) ) finsi si diff --git a/src/mlang/backend_compilers/bir_to_dgfip_c.ml b/src/mlang/backend_compilers/bir_to_dgfip_c.ml index ee9aed24e..fb470914b 100644 --- a/src/mlang/backend_compilers/bir_to_dgfip_c.ml +++ b/src/mlang/backend_compilers/bir_to_dgfip_c.ml @@ -165,6 +165,28 @@ let rec lis_tabaccess (p : Mir.program) m_sp_opt v m_idx = let value_comp = D.dinstr res_val in D.build_transitive_composition { set_vars; def_test; value_comp } +and code_access (p : Mir.program) m_acc = + let d_irdata = D.ddirect (D.dinstr "irdata") in + match Pos.unmark m_acc with + | Com.VarAccess (_, v) -> ([], D.ddirect @@ D.dinstr @@ VID.gen_info_ptr v) + | Com.TabAccess ((_, v), m_i) -> + let ei = generate_c_expr p m_i in + let d_fun = + D.dfun "lis_tabaccess_varinfo" + [ + d_irdata; + D.ddirect @@ D.dinstr @@ Pp.spr "%d" (Com.Var.loc_tab_idx v); + ei.def_test; + ei.value_comp; + ] + in + (ei.set_vars, D.ddirect @@ d_fun) + | Com.FieldAccess (_, ie, f, _) -> + let e = generate_c_expr p ie in + let fn = Pp.spr "event_field_%s_var" (Pos.unmark f) in + let d_fun = D.dfun fn [ d_irdata; e.def_test; e.value_comp ] in + (e.set_vars, D.ddirect d_fun) + and generate_c_expr (p : Mir.program) (e : Mir.expression Pos.marked) : D.expression_composition = let comparison op se1 se2 = @@ -245,7 +267,7 @@ and generate_c_expr (p : Mir.program) (e : Mir.expression Pos.marked) : D.{ set_vars = []; def_test; value_comp } in comparison (Pos.without Com.Eq) sle0 s_v - | Com.VarValue (Pos.Mark (TabAccess (m_sp_opt, v, m_i), _)) -> + | Com.VarValue (Pos.Mark (TabAccess ((m_sp_opt, v), m_i), _)) -> let s_v = lis_tabaccess p m_sp_opt v m_i in comparison (Pos.without Com.Eq) sle0 s_v | Com.VarValue (Pos.Mark (FieldAccess (m_sp_opt, me, f, _), _)) -> @@ -491,7 +513,7 @@ and generate_c_expr (p : Mir.program) (e : Mir.expression Pos.marked) : let def_test = D.m_var m_sp_opt var Def in let value_comp = D.m_var m_sp_opt var Val in { set_vars = []; def_test; value_comp } - | Var (TabAccess (m_sp_opt, v, m_idx)) -> lis_tabaccess p m_sp_opt v m_idx + | Var (TabAccess ((m_sp_opt, v), m_idx)) -> lis_tabaccess p m_sp_opt v m_idx | Var (FieldAccess (m_sp_opt, me, f, _)) -> let fn = Pp.spr "event_field_%s" (Pos.unmark f) in let res = fresh_c_local "result" in @@ -526,7 +548,7 @@ and generate_c_expr (p : Mir.program) (e : Mir.expression Pos.marked) : | Attribut (m_acc, a) -> ( let attr = Pos.unmark a in match Pos.unmark m_acc with - | VarAccess (_, v) | TabAccess (_, v, _) -> + | VarAccess (_, v) | TabAccess ((_, v), _) -> let ptr = VID.gen_info_ptr v in let def_test = D.dinstr (Pp.spr "attribut_%s_def((T_varinfo *)%s)" attr ptr) @@ -596,7 +618,7 @@ and generate_c_expr (p : Mir.program) (e : Mir.expression Pos.marked) : match Pos.unmark m_acc with | Com.VarAccess (_, v) -> ([], D.ddirect @@ D.dinstr @@ VID.gen_info_ptr v) - | Com.TabAccess (_, v, m_i) -> + | Com.TabAccess ((_, v), m_i) -> let ei = generate_c_expr p m_i in let d_fun = D.dfun "lis_tabaccess_varinfo" @@ -648,31 +670,8 @@ and generate_c_expr (p : Mir.program) (e : Mir.expression Pos.marked) : let value_comp = D.dinstr res_val in D.build_transitive_composition { set_vars; def_test; value_comp } | SameVariable (m_acc0, m_acc1) -> - let d_irdata = D.ddirect (D.dinstr "irdata") in - let code_access m_acc = - match Pos.unmark m_acc with - | Com.VarAccess (_, v) -> - ([], D.ddirect @@ D.dinstr @@ VID.gen_info_ptr v) - | Com.TabAccess (_, v, m_i) -> - let ei = generate_c_expr p m_i in - let d_fun = - D.dfun "lis_tabaccess_varinfo" - [ - d_irdata; - D.ddirect @@ D.dinstr @@ Pp.spr "%d" (Com.Var.loc_tab_idx v); - ei.def_test; - ei.value_comp; - ] - in - (ei.set_vars, D.ddirect @@ d_fun) - | Com.FieldAccess (_, ie, f, _) -> - let e = generate_c_expr p ie in - let fn = Pp.spr "event_field_%s_var" (Pos.unmark f) in - let d_fun = D.dfun fn [ d_irdata; e.def_test; e.value_comp ] in - (e.set_vars, D.ddirect d_fun) - in - let set_vars0, evt_d_fun0 = code_access m_acc0 in - let set_vars1, evt_d_fun1 = code_access m_acc1 in + let set_vars0, evt_d_fun0 = code_access p m_acc0 in + let set_vars1, evt_d_fun1 = code_access p m_acc1 in let res = fresh_c_local "res" in let res_def = Pp.spr "%s_def" res in let res_val = Pp.spr "%s_val" res in @@ -727,7 +726,7 @@ and generate_c_expr (p : Mir.program) (e : Mir.expression Pos.marked) : let def_test = D.dinstr res_def in let value_comp = D.dinstr res_val in D.build_transitive_composition { set_vars; def_test; value_comp } - | TabAccess (_, v, m_i) -> + | TabAccess ((_, v), m_i) -> let d_irdata = D.ddirect (D.dinstr "irdata") in let res = fresh_c_local "res" in let res_def = Pp.spr "%s_def" res in @@ -809,9 +808,9 @@ and generate_c_expr (p : Mir.program) (e : Mir.expression Pos.marked) : D.build_transitive_composition { set_vars = []; def_test; value_comp } | NbCategory _ | FuncCallLoop _ | Loop _ -> assert false -let generate_expr_with_res_in p dgfip_flags oc res_def res_val expr = +let write_decoupled_expr dgfip_flags oc res_def res_val (locals, set, def, value) + = let pr form = Format.fprintf oc form in - let locals, set, def, value = D.build_expression @@ generate_c_expr p expr in if D.is_always_true def then pr "@;@[{%a%a%a%a@]@;}" D.format_local_declarations locals (D.format_set_vars dgfip_flags) @@ -830,6 +829,10 @@ let generate_expr_with_res_in p dgfip_flags oc res_def res_val expr = (D.format_assign dgfip_flags res_val) value res_val +let generate_expr_with_res_in p dgfip_flags oc res_def res_val expr = + generate_c_expr p expr |> D.build_expression + |> write_decoupled_expr dgfip_flags oc res_def res_val + let generate_m_assign (p : Mir.program) (dgfip_flags : Dgfip_options.flags) (m_sp_opt : Com.var_space) (var : Com.Var.t) (oc : Format.formatter) (expr : Mir.expression Pos.marked) : unit = @@ -944,7 +947,7 @@ let rec generate_stmt (env : env) (dgfip_flags : Dgfip_options.flags) match Pos.unmark m_acc with | VarAccess (m_sp_opt, v) -> generate_var_def p dgfip_flags m_sp_opt v expr oc - | TabAccess (m_sp_opt, v, m_idx) -> + | TabAccess ((m_sp_opt, v), m_idx) -> generate_var_def_tab p dgfip_flags m_sp_opt v m_idx expr oc | FieldAccess (m_sp_opt, i, f, _) -> let fn = Pos.unmark f in @@ -968,7 +971,6 @@ let rec generate_stmt (env : env) (dgfip_flags : Dgfip_options.flags) pr "@]@;}"; pr "@]@;}" | Switch (e, l) -> - pr "@;@[{"; (* Undef & Default should be unique, but just in case we take them all *) let undef_branches, default_branches, other_branches = List.fold_left @@ -976,9 +978,10 @@ let rec generate_stmt (env : env) (dgfip_flags : Dgfip_options.flags) List.fold_left (fun (und, def, oth) c -> match c with - | Com.Default -> (und, l :: def, oth) - | Com.(Value Undefined) -> (l :: und, def, oth) - | Com.(Value (Float f)) -> (und, def, (f, l) :: oth)) + | Com.CDefault -> (und, l :: def, oth) + | Com.(CValue Undefined) -> (l :: und, def, oth) + | Com.(CValue (Float f)) -> (und, def, (`Float f, l) :: oth) + | Com.CVar v -> (und, def, (`Var v, l) :: oth)) acc cl) ([], [], []) l in @@ -988,42 +991,85 @@ let rec generate_stmt (env : env) (dgfip_flags : Dgfip_options.flags) let exp = fresh_c_local "exp" in let exp_def = exp ^ "_def" in let exp_val = exp ^ "_val" in + let is_var_switch = + match e with SESameVariable _ -> true | SEValue _ -> false + in + let var_of_switch () = + assert is_var_switch; + match e with SESameVariable e -> e | _ -> assert false + in + pr "@;@[{"; pr "@;char %s;@;double %s;" exp_def exp_val; - generate_expr_with_res_in p dgfip_flags oc exp_def exp_val e; - pr "@;@[if (%s) {" exp_def; - pr "@;"; + let () = + (* Check is def if necessary *) + match e with + | SESameVariable _ -> pr "{@;" + | SEValue e -> + generate_expr_with_res_in p dgfip_flags oc exp_def exp_val e; + pr "@;@[if (%s) {@;" exp_def + in + pr "// Switch cases @;"; (* Expression is defined *) let () = + let pp_case (v, br) = + match v with + | `Float v -> + assert (not is_var_switch); + pr "if (EQ_E((%s),(%#.19g))) {@;@[%a@]@;}" exp_val v + (generate_stmts env dgfip_flags p) + br + | `Var v -> + assert is_var_switch; + let e = var_of_switch () in + let compared_var = Pos.unmark e in + let is_same = fresh_c_local "is_same_var" in + let is_same_def = is_same ^ "_def" in + let is_same_val = is_same ^ "_val" in + pr "@;char %s;@;double %s;" is_same_def is_same_val; + let ex = + Pos.same (Com.SameVariable (v, Pos.same compared_var e)) e + in + generate_expr_with_res_in p dgfip_flags oc is_same_def is_same_val + ex; + pr "if (%s) {@;@[%a@]@;}" is_same_val + (generate_stmts env dgfip_flags p) + br + in + let rec loop_else = function + | [] -> ( + (* Default branch *) + match (default_branches, other_branches) with + | [], _ -> () + | hd :: _, [] -> + pr "// Default switch case@;"; + pr "@;@[%a@]" (generate_stmts env dgfip_flags p) hd + | hd :: _, _ -> + pr "// Default switch case@;"; + pr "@;else {@[%a@]@;}" + (generate_stmts env dgfip_flags p) + hd) + | c :: tl -> + pr "else {@;@[ "; + pp_case c; + loop_else tl; + pr "@]@;}@;" + in match other_branches with | [] -> () - | (v, br) :: tl -> - pr "if (EQ_E((%s),(%#.19g))) {@;@[%a@]@;}" exp_val v - (generate_stmts env dgfip_flags p) - br; - List.iter - (fun (v, br) -> - pr "@; else if (EQ_E((%s),(%#.19g))) {@;@[%a@]@;}" exp_val - v - (generate_stmts env dgfip_flags p) - br) - tl - in - let () = - match (default_branches, other_branches) with - | [], _ -> () - | hd :: _, [] -> - pr "@;@[%a@]" (generate_stmts env dgfip_flags p) hd - | hd :: _, _ -> - pr "@;else {@[%a@]@;}" (generate_stmts env dgfip_flags p) hd + | c :: tl -> + pp_case c; + loop_else tl in - pr "@;}"; + pr "}@;// End of switch cases & default@;"; (* Expression is undefined *) let () = match undef_branches with | [] -> () - | hd :: _ -> pr " else %a" (generate_stmts env dgfip_flags p) hd + | hd :: _ -> + pr "// Undefined switch case@;"; + pr " else %a" (generate_stmts env dgfip_flags p) hd in - pr "@]@;}@]" + pr "@]}" | WhenDoElse (wdl, ed) -> let goto_label = fresh_c_local "when_do_block" in let fin_label = fresh_c_local "when_do_end" in @@ -1093,7 +1139,7 @@ let rec generate_stmt (env : env) (dgfip_flags : Dgfip_options.flags) match info with Com.Name -> "name" | Com.Alias -> "alias" in pr "@;print_string(%s, %s, %s->%s);" print_std pr_ctx ptr fld - | TabAccess (m_sp_opt, v, m_idx) -> + | TabAccess ((m_sp_opt, v), m_idx) -> pr_sp m_sp_opt (Some v); pr "@;@[{"; pr "T_varinfo *info;"; @@ -1167,7 +1213,7 @@ let rec generate_stmt (env : env) (dgfip_flags : Dgfip_options.flags) pr "@;%s = %s;" ref_val (VID.gen_val_ptr m_sp_opt var); pr "@]@;}"; set_args (n + 1) vl' al' - | Com.TabAccess (m_sp_opt, var, vidx) -> + | Com.TabAccess ((m_sp_opt, var), vidx) -> pr "@;@[if (must_exec) {"; let idx_tab = Com.Var.loc_tab_idx var in pr "@;T_varinfo *info = tab_varinfo[%d];" idx_tab; @@ -1253,7 +1299,7 @@ let rec generate_stmt (env : env) (dgfip_flags : Dgfip_options.flags) pr "@;%s = %s;" ref_val (VID.gen_val_ptr m_sp_opt v); pr "%a" (generate_stmts env dgfip_flags p) stmts; pr "@]@;}" - | Com.TabAccess (m_sp_opt, var, vidx) -> + | Com.TabAccess ((m_sp_opt, var), vidx) -> pr "@;@[{"; let idx_tab = Com.Var.loc_tab_idx var in pr "@;T_varinfo *info = tab_varinfo[%d];" idx_tab; @@ -1552,7 +1598,7 @@ let rec generate_stmt (env : env) (dgfip_flags : Dgfip_options.flags) let sz = VID.gen_size var in pr "@;env_sauvegarder(&%s, %s, %s, %s);" rest_name def_ptr val_ptr sz - | Com.TabAccess (m_sp_opt, var, vidx) -> + | Com.TabAccess ((m_sp_opt, var), vidx) -> pr "@;@[{"; let idx_tab = Com.Var.loc_tab_idx var in pr "@;T_varinfo *info = tab_varinfo[%d];" idx_tab; diff --git a/src/mlang/m_frontend/expander.ml b/src/mlang/m_frontend/expander.ml index c3a3adda8..7c00a4a4e 100644 --- a/src/mlang/m_frontend/expander.ml +++ b/src/mlang/m_frontend/expander.ml @@ -583,7 +583,7 @@ let rec expand_access (const_map : const_context) (loop_map : loop_context) | Pos.Mark (AtomVar m_v', _) -> let a' = Com.VarAccess (m_sp_opt', m_v') in ExpAccess (Pos.mark a' a_pos)) - | TabAccess (m_sp_opt, m_v, m_i) -> ( + | TabAccess ((m_sp_opt, m_v), m_i) -> ( match expand_variable const_map loop_map m_v with | Pos.Mark (AtomLiteral _, v_pos) -> Err.constant_forbidden_as_table v_pos | Pos.Mark (AtomVar m_v', _) -> @@ -597,7 +597,7 @@ let rec expand_access (const_map : const_context) (loop_map : loop_context) m_sp_opt in let m_i' = expand_expression const_map loop_map m_i in - let a' = Com.TabAccess (m_sp_opt', m_v', m_i') in + let a' = Com.TabAccess ((m_sp_opt', m_v'), m_i') in ExpAccess (Pos.mark a' a_pos)) | FieldAccess (m_sp_opt, e, f, i_f) -> let m_sp_opt' = @@ -612,6 +612,14 @@ let rec expand_access (const_map : const_context) (loop_map : loop_context) let e' = expand_expression const_map loop_map e in ExpAccess (Pos.mark (Com.FieldAccess (m_sp_opt', e', f, i_f)) a_pos) +and expand_switch_expression (const_map : const_context) + (loop_map : loop_context) = function + | Com.SEValue e -> Com.SEValue (expand_expression const_map loop_map e) + | SESameVariable v -> ( + match expand_access const_map loop_map v with + | ExpAccess m_a -> SESameVariable m_a + | ExpLiteral _ -> SESameVariable v) + and expand_expression (const_map : const_context) (loop_map : loop_context) (m_expr : Mast.expression Pos.marked) : Mast.expression Pos.marked = let open Com in @@ -766,6 +774,14 @@ let expand_formula (const_map : const_context) let res = loop_context_provider translator in List.rev res @ prev +let expand_switch_case const_map loop_map c = + match c with + | Com.CVar e -> ( + match expand_access const_map loop_map e with + | ExpLiteral l -> Com.CValue l + | ExpAccess a -> Com.CVar a) + | CValue _ | CDefault -> c + let rec expand_instruction (const_map : const_context) (prev : Mast.instruction Pos.marked list) (m_instr : Mast.instruction Pos.marked) : Mast.instruction Pos.marked list = @@ -781,9 +797,18 @@ let rec expand_instruction (const_map : const_context) let ielse' = expand_instructions const_map ielse in Pos.same (Com.IfThenElse (expr', ithen', ielse')) m_instr :: prev | Com.Switch (e, l) -> - let e' = expand_expression const_map ParamsMap.empty e in + let e' = expand_switch_expression const_map ParamsMap.empty e in let l' = - List.map (fun (c, l) -> (c, expand_instructions const_map l)) l + List.map + (fun (cl, l) -> + let cl = + match e with + | SESameVariable _ -> cl + | SEValue _ -> + List.map (expand_switch_case const_map ParamsMap.empty) cl + in + (cl, expand_instructions const_map l)) + l in Pos.same (Com.Switch (e', l')) m_instr :: prev | Com.WhenDoElse (wdl, ed) -> diff --git a/src/mlang/m_frontend/mast_to_mir.ml b/src/mlang/m_frontend/mast_to_mir.ml index ea2b26b90..5723320f4 100644 --- a/src/mlang/m_frontend/mast_to_mir.ml +++ b/src/mlang/m_frontend/mast_to_mir.ml @@ -348,7 +348,7 @@ let complete_stats ((prog : Validator.program), (stats : Mir.stats)) : and aux_access tdata m_a = match Pos.unmark m_a with | Com.VarAccess _ -> (0, 0, 0, tdata) - | Com.TabAccess (_, _, mi) | Com.FieldAccess (_, mi, _, _) -> + | Com.TabAccess (_, mi) | Com.FieldAccess (_, mi, _, _) -> aux_expr tdata mi and aux_instr tdata (Pos.Mark (instr, _pos)) = match instr with @@ -382,7 +382,7 @@ let complete_stats ((prog : Validator.program), (stats : Mir.stats)) : let nbRef = max nbRefI @@ max nbRefT nbRefE in (nb, sz, nbRef, tdata) | Com.Switch (expr, l) -> - let nbI, szI, nbRefI, tdata = aux_expr tdata expr in + let nbI, szI, nbRefI, tdata = aux_switch_expr tdata expr in List.fold_left (fun (mNb, mSz, mNbRef, tdata) (_, l) -> let nb, sz, rbRef, tdata = aux_instrs tdata l in @@ -527,11 +527,15 @@ let complete_stats ((prog : Validator.program), (stats : Mir.stats)) : (0, 0, 0, tdata) | Com.ComputeDomain _ | Com.ComputeChaining _ | Com.ComputeVerifs _ -> assert false + and aux_switch_expr tdata se = + match se with + | Com.SEValue e -> aux_expr tdata e + | Com.SESameVariable m -> aux_access tdata m and aux_expr tdata (Pos.Mark (expr, _pos)) = match expr with | Com.TestInSet (_, me, values) -> let fold (nb, sz, nbRef, tdata) = function - | Com.VarValue (Pos.Mark (TabAccess (_, _, mei), _)) + | Com.VarValue (Pos.Mark (TabAccess (_, mei), _)) | Com.VarValue (Pos.Mark (FieldAccess (_, mei, _, _), _)) -> let nb', sz', nbRef', tdata = aux_expr tdata mei in (max nb nb', max sz sz', max nbRef nbRef', tdata) @@ -543,26 +547,25 @@ let complete_stats ((prog : Validator.program), (stats : Mir.stats)) : let nb'', sz'', nbRef'', tdata = aux_expr tdata me in (max nb' nb'', max sz' sz'', max nbRef' nbRef'', tdata) | Com.Unop (_, me) - | Com.Var (TabAccess (_, _, me)) + | Com.Var (TabAccess (_, me)) | Com.Var (FieldAccess (_, me, _, _)) - | Com.Size (Pos.Mark (TabAccess (_, _, me), _)) + | Com.Size (Pos.Mark (TabAccess (_, me), _)) | Com.Size (Pos.Mark (FieldAccess (_, me, _, _), _)) - | Com.Type (Pos.Mark (TabAccess (_, _, me), _), _) + | Com.Type (Pos.Mark (TabAccess (_, me), _), _) | Com.Type (Pos.Mark (FieldAccess (_, me, _, _), _), _) - | Com.Attribut (Pos.Mark (TabAccess (_, _, me), _), _) + | Com.Attribut (Pos.Mark (TabAccess (_, me), _), _) | Com.Attribut (Pos.Mark (FieldAccess (_, me, _, _), _), _) -> aux_expr tdata me | Com.Comparison (_, me0, me1) | Com.Binop (_, me0, me1) | Com.SameVariable - ( Pos.Mark (TabAccess (_, _, me0), _), - Pos.Mark (TabAccess (_, _, me1), _) ) + (Pos.Mark (TabAccess (_, me0), _), Pos.Mark (TabAccess (_, me1), _)) | Com.SameVariable - ( Pos.Mark (TabAccess (_, _, me0), _), + ( Pos.Mark (TabAccess (_, me0), _), Pos.Mark (FieldAccess (_, me1, _, _), _) ) | Com.SameVariable ( Pos.Mark (FieldAccess (_, me0, _, _), _), - Pos.Mark (TabAccess (_, _, me1), _) ) + Pos.Mark (TabAccess (_, me1), _) ) | Com.SameVariable ( Pos.Mark (FieldAccess (_, me0, _, _), _), Pos.Mark (FieldAccess (_, me1, _, _), _) ) -> @@ -687,7 +690,7 @@ let rec translate_expression (p : Validator.program) (dict : Com.Var.t IntMap.t) match StrMap.find_opt (Pos.unmark a) (Com.Var.attrs var) with | Some l -> Literal (Float (float (Pos.unmark l))) | None -> Literal Undefined) - | TabAccess (_, m_id, _) -> ( + | TabAccess ((_, m_id), _) -> ( let var = get_var dict m_id in match StrMap.find_opt (Pos.unmark a) (Com.Var.attrs var) with | Some l -> Literal (Float (float (Pos.unmark l))) @@ -769,17 +772,31 @@ and translate_access (p : Validator.program) (dict : Com.Var.t IntMap.t) let m_sp_opt' = trans_m_sp_opt m_sp_opt in let v' = get_var dict m_v in Com.VarAccess (m_sp_opt', v') - | TabAccess (m_sp_opt, m_v, m_i) -> + | TabAccess ((m_sp_opt, m_v), m_i) -> let m_sp_opt' = trans_m_sp_opt m_sp_opt in let v' = get_var dict m_v in let m_i' = translate_expression p dict m_i in - Com.TabAccess (m_sp_opt', v', m_i') + Com.TabAccess ((m_sp_opt', v'), m_i') | FieldAccess (m_sp_opt, i, f, _) -> let m_sp_opt' = trans_m_sp_opt m_sp_opt in let i' = translate_expression p dict i in let ef = StrMap.find (Pos.unmark f) p.prog_event_fields in Com.FieldAccess (m_sp_opt', i', f, ef.index) +and translate_switch_expression (p : Validator.program) + (dict : Com.Var.t IntMap.t) = function + | Com.SEValue v -> Com.SEValue (translate_expression p dict v) + | SESameVariable v -> + SESameVariable (Pos.same (translate_access p dict (Pos.unmark v)) v) + +let translate_case (p : Validator.program) (dict : Com.Var.t IntMap.t) + (case : int Pos.marked Com.case) : Com.Var.t Com.case = + match case with + | CDefault -> CDefault + | CValue v -> CValue v + | CVar (Pos.Mark (acc, pos)) -> + CVar (Pos.mark (translate_access p dict acc) pos) + (** {2 Translation of instructions} *) let rec translate_prog (p : Validator.program) (dict : Com.Var.t IntMap.t) @@ -813,12 +830,13 @@ let rec translate_prog (p : Validator.program) (dict : Com.Var.t IntMap.t) let instr' = Com.IfThenElse (expr, prog_then, prog_else) in aux (Pos.mark instr' pos :: res, dict) il | Pos.Mark (Com.Switch (e, l), pos) :: il -> - let e' = translate_expression p dict e in + let e' = translate_switch_expression p dict e in let revl', dict = List.fold_left (fun (revl, dict) (c, l) -> + let c' = List.map (translate_case p dict) c in let l', dict = aux ([], dict) l in - ((c, l') :: revl, dict)) + ((c', l') :: revl, dict)) ([], dict) l in let i' = Com.Switch (e', List.rev revl') in diff --git a/src/mlang/m_frontend/mlexer.mll b/src/mlang/m_frontend/mlexer.mll index 543c757ce..411390596 100644 --- a/src/mlang/m_frontend/mlexer.mll +++ b/src/mlang/m_frontend/mlexer.mll @@ -94,7 +94,6 @@ rule token = parse | "erreur" -> ERROR | "espace" -> SPACE | "espace_variables" -> VARIABLE_SPACE - | "meme_variable" -> SAME_VARIABLE | "et" -> AND | "evenement" -> EVENT | "evenements" -> EVENTS @@ -111,6 +110,7 @@ rule token = parse | "informative" -> INFORMATIVE | "iterer" -> ITERATE | "leve_erreur" -> RAISE_ERROR + | "meme_variable" -> SAME_VARIABLE | "nb_bloquantes" -> NB_BLOCKING | "nb_categorie" -> NB_CATEGORY | "nb_anomalies" -> NB_ANOMALIES diff --git a/src/mlang/m_frontend/mparser.mly b/src/mlang/m_frontend/mparser.mly index 51f38dbe8..ad0595d1e 100644 --- a/src/mlang/m_frontend/mparser.mly +++ b/src/mlang/m_frontend/mparser.mly @@ -883,13 +883,30 @@ instruction: | STOP TARGET SEMICOLON { Some (Stop SKTarget) } | STOP s = SYMBOL SEMICOLON { Some (Stop (SKId (Some s))) } | STOP SEMICOLON { Some (Stop (SKId None)) } -| MATCH LPAREN e = with_pos(expression) RPAREN COLON LPAREN l = nonempty_list(switch_case) RPAREN - { Some (Switch (e, l)) } +| s = switch_kind COLON LPAREN l = nonempty_list(switch_case) RPAREN + { Some (Switch (s, l)) } + +switch_kind: + | MATCH NAME LPAREN acc = with_pos(var_access) RPAREN { Com.SESameVariable acc } + | MATCH LPAREN e = with_pos(expression) RPAREN { Com.SEValue e } + +switch_case_kind: + | s = SYMBOL + { + let pos = mk_position $sloc in + match parse_literal $sloc s with + | l -> Com.CValue l + | exception (Errors.StructuredError _) -> + match parse_variable_or_int $sloc s with + | ParseVar v -> + Com.CVar (Pos.mark (Com.VarAccess (None, Pos.mark v pos)) pos) + | ParseInt i -> Com.CValue (Float (float_of_int i)) + } + | UNDEFINED { Com.CValue Com.Undefined } switch_case_value: -| CASE s = SYMBOL COLON { Value (Com.Float (float_of_string s)) } -| CASE UNDEFINED COLON { Value Com.Undefined } -| BY_DEFAULT COLON { Com.Default } +| CASE sck = switch_case_kind COLON { sck } +| BY_DEFAULT COLON { Com.CDefault } switch_cases_rev: | sc = switch_case_value { [ sc ] } @@ -1135,13 +1152,13 @@ var_access: let m_v = Pos.same (parse_variable $sloc (Pos.unmark v)) v in match m_i_opt with | None -> Com.VarAccess (Some (m_sp, -1), m_v) - | Some m_i -> Com.TabAccess (Some (m_sp, -1), m_v, m_i) + | Some m_i -> Com.TabAccess ((Some (m_sp, -1), m_v), m_i) } | v = symbol_with_pos m_i_opt = with_pos(brackets)? { let m_v = Pos.same (parse_variable $sloc (Pos.unmark v)) v in match m_i_opt with | None -> Com.VarAccess (None, m_v) - | Some m_i -> Com.TabAccess (None, m_v, m_i) + | Some m_i -> Com.TabAccess ((None, m_v), m_i) } | sp = symbol_with_pos DOT EVENT_FIELD LPAREN idx = with_pos(expression) COMMA f = symbol_with_pos RPAREN { @@ -1343,13 +1360,13 @@ enumeration_item: let a = match m_i_opt with | None -> Com.VarAccess (Some (m_sp, -1), m_v) - | Some m_i -> Com.TabAccess (Some (m_sp, -1), m_v, m_i) + | Some m_i -> Com.TabAccess ((Some (m_sp, -1), m_v), m_i) in Com.VarValue (Pos.mark a (mk_position $sloc)) } | v = symbol_with_pos LBRACKET m_i = with_pos(expression) RBRACKET { let m_v = Pos.same (parse_variable $sloc (Pos.unmark v)) v in - let a = Com.TabAccess (None, m_v, m_i) in + let a = Com.TabAccess ((None, m_v), m_i) in Com.VarValue (Pos.mark a (mk_position $sloc)) } | v = SYMBOL { @@ -1436,11 +1453,11 @@ factor: LBRACKET m_i = with_pos(sum_expression) RBRACKET { let m_sp = Pos.same (parse_variable $sloc (Pos.unmark sp)) sp in let m_v = Pos.same (parse_variable $sloc (Pos.unmark v)) v in - Var (TabAccess (Some (m_sp, -1), m_v, m_i)) + Var (TabAccess ((Some (m_sp, -1), m_v), m_i)) } | v = symbol_with_pos LBRACKET m_i = with_pos(sum_expression) RBRACKET { let m_v = Pos.same (parse_variable $sloc (Pos.unmark v)) v in - Var (TabAccess (None, m_v, m_i)) + Var (TabAccess ((None, m_v), m_i)) } | sp = symbol_with_pos DOT v = symbol_with_pos { let m_sp = Pos.same (parse_variable $sloc (Pos.unmark sp)) sp in diff --git a/src/mlang/m_frontend/validator.ml b/src/mlang/m_frontend/validator.ml index 11d88823b..645e35306 100644 --- a/src/mlang/m_frontend/validator.ml +++ b/src/mlang/m_frontend/validator.ml @@ -427,9 +427,39 @@ module Err = struct Errors.raise_spanned_error msg pos let non_exclusive_cases case pos = + let format_var_name fmt v = + Format.fprintf fmt "%s" (Com.get_var_name (Pos.unmark v)) + in let msg = Pp.spr "switch cases must be exclusive: %a cannot be used twice" - Com.format_case case + (Com.format_case format_var_name + (Com.format_expression format_var_name)) + case + in + Errors.raise_spanned_error msg pos + + let forbidden_value_check_in_switch case pos = + let format_var_name fmt v = + Format.fprintf fmt "%s" (Com.get_var_name (Pos.unmark v)) + in + let msg = + Pp.spr "switch case %a is invalid: cannot match a value in a name switch" + (Com.format_case format_var_name + (Com.format_expression format_var_name)) + case + in + Errors.raise_spanned_error msg pos + + let forbidden_variable_check_in_switch case pos = + let format_var_name fmt v = + Format.fprintf fmt "%s" (Com.get_var_name (Pos.unmark v)) + in + let msg = + Pp.spr + "switch case %a is invalid: cannot match a variable in a value switch" + (Com.format_case format_var_name + (Com.format_expression format_var_name)) + case in Errors.raise_spanned_error msg pos end @@ -1255,7 +1285,7 @@ let rec fold_var_expr (get_var : 'v -> string Pos.marked) | VarAccess (m_sp_opt, m_v) -> let acc = fold_sp m_sp_opt env acc in fold_var m_sp_opt m_v Num env acc - | TabAccess (m_sp_opt, m_v, m_i) -> + | TabAccess ((m_sp_opt, m_v), m_i) -> let acc = fold_sp m_sp_opt env acc in let acc = fold_var m_sp_opt m_v Table env acc in fold_aux acc m_i env @@ -1339,7 +1369,7 @@ let rec fold_var_expr (get_var : 'v -> string Pos.marked) | VarAccess (m_sp_opt, m_v) -> let acc = fold_sp m_sp_opt env acc in fold_var m_sp_opt m_v Num env acc - | TabAccess (m_sp_opt, m_v, m_i) -> + | TabAccess ((m_sp_opt, m_v), m_i) -> let acc = fold_sp m_sp_opt env acc in let acc = fold_var m_sp_opt m_v Table env acc in fold_aux acc m_i env @@ -1375,7 +1405,7 @@ let rec fold_var_expr (get_var : 'v -> string Pos.marked) | None -> Err.unknown_variable var_pos); let acc = fold_sp m_sp_opt env acc in fold_var m_sp_opt m_v Both env acc - | TabAccess (m_sp_opt, m_v, m_i) -> + | TabAccess ((m_sp_opt, m_v), m_i) -> let name, var_pos = Pos.to_couple @@ get_var m_v in (match StrMap.find_opt name env.vars with | Some id -> @@ -1415,7 +1445,7 @@ let rec fold_var_expr (get_var : 'v -> string Pos.marked) | VarAccess (m_sp_opt, m_v) -> let acc = fold_sp m_sp_opt env acc in fold_var m_sp_opt m_v Both env acc - | TabAccess (m_sp_opt, m_v, m_i) -> + | TabAccess ((m_sp_opt, m_v), m_i) -> let acc = fold_sp m_sp_opt env acc in let acc = fold_var m_sp_opt m_v Table env acc in fold_aux acc m_i env @@ -1435,7 +1465,7 @@ let rec fold_var_expr (get_var : 'v -> string Pos.marked) | Com.VarAccess (m_sp_opt, m_v) -> let acc = fold_sp m_sp_opt env acc in fold_var m_sp_opt m_v Both env acc - | Com.TabAccess (m_sp_opt, m_v, m_i) -> + | Com.TabAccess ((m_sp_opt, m_v), m_i) -> let acc = fold_sp m_sp_opt env acc in let acc = fold_var m_sp_opt m_v Table env acc in fold_aux acc m_i env @@ -1639,12 +1669,12 @@ let rec check_instructions (env : var_env) check_variable m_sp_opt m_v mem_var env; let m_v' = map_var env m_v in Pos.mark (Com.VarAccess (m_sp_opt, m_v')) apos - | Com.TabAccess (m_sp_opt, m_v, m_i) -> + | Com.TabAccess ((m_sp_opt, m_v), m_i) -> check_var_space m_sp_opt env; check_variable m_sp_opt m_v Table env; let m_v' = map_var env m_v in let m_i' = map_expr env m_i in - Pos.mark (Com.TabAccess (m_sp_opt, m_v', m_i')) apos + Pos.mark (Com.TabAccess ((m_sp_opt, m_v'), m_i')) apos | Com.FieldAccess (m_sp_opt, m_i, f, id) -> if env.proc_type = Rule then Err.instruction_forbidden_in_rules (Pos.get m_a); @@ -1659,6 +1689,19 @@ let rec check_instructions (env : var_env) let a' = Com.FieldAccess (m_sp_opt, m_i', f, id) in Pos.mark a' apos in + let map_switch_expr env = function + | Com.SEValue e -> Com.SEValue (map_expr env e) + | SESameVariable v -> + SESameVariable (check_m_access ~onlyVar:true Both env v) + in + let check_case env c = + match c with + | Com.CDefault -> Com.CDefault + | CValue v -> CValue v + | CVar acc -> + let acc' = check_m_access ~onlyVar:true Both env acc in + CVar acc' + in let rec aux ((env, res) : var_env * (int Pos.marked, Mast.error_name) Com.m_instruction list) @@ -1827,12 +1870,12 @@ let rec check_instructions (env : var_env) check_var_space m_sp_opt env; check_variable m_sp_opt v Both env; Com.VarAccess (m_sp_opt, map_var env v) - | Com.TabAccess (m_sp_opt, m_v, m_i) -> + | Com.TabAccess ((m_sp_opt, m_v), m_i) -> check_var_space m_sp_opt env; check_variable m_sp_opt m_v Table env; let m_v' = map_var env m_v in let m_i' = map_expr env m_i in - Com.TabAccess (m_sp_opt, m_v', m_i') + Com.TabAccess ((m_sp_opt, m_v'), m_i') | Com.FieldAccess (m_sp_opt, e, f, id) -> ( let f_name, f_pos = Pos.to_couple f in check_var_space m_sp_opt env; @@ -2031,15 +2074,45 @@ let rec check_instructions (env : var_env) let instr' = Com.ArrangeEvents (sort', filter', add', instrs') in aux (env, Pos.mark instr' instr_pos :: res) il | Com.Switch (e, l) -> - let e' = map_expr env e in + let e' = map_switch_expr env e in + let kind_is_same_var = + match e' with + | Com.SESameVariable _ -> true + | Com.SEValue _ -> false + in + let case_is_var = function + | Com.CVar _ | CDefault -> true + | CValue _ -> false + in + let case_is_val = function + | Com.CValue _ | CDefault -> true + | CVar _ -> false + in let _cases, env, rev_l' = List.fold_left (fun (cases, env, rev_l') (cl, l) -> - match List.find (fun c -> List.mem c cases) cl with - | c -> Err.non_exclusive_cases c instr_pos - | exception Not_found -> - let prog, l'elt = check_instructions env l in - (cl @ cases, { env with prog }, (cl, l'elt) :: rev_l')) + (* Check if variable checks are made in name switches only *) + let () = + if kind_is_same_var then + match List.find (fun v -> not (case_is_var v)) cl with + | case -> + Err.forbidden_value_check_in_switch case instr_pos + | exception Not_found -> () + else + match List.find (fun v -> not (case_is_val v)) cl with + | case -> + Err.forbidden_variable_check_in_switch case instr_pos + | exception Not_found -> () + in + let () = + match List.find (fun c -> List.mem c cases) cl with + | c -> Err.non_exclusive_cases c instr_pos + | exception Not_found -> () + in + let prog, l'elt = check_instructions env l in + let env = { env with prog } in + let cl' = List.map (check_case env) cl in + (cl @ cases, env, (cl', l'elt) :: rev_l')) ([], env, []) l in let l' = List.rev rev_l' in @@ -2118,6 +2191,13 @@ let inout_expression (env : var_env) (m_expr : int Pos.marked Com.m_expression) in fold_var_expr get_var fold_sp fold_var StrMap.empty m_expr env +let inout_switch_expression (env : var_env) + (s_e : int Pos.marked Com.switch_expression) = + match s_e with + | SEValue v -> inout_expression env v + | SESameVariable m -> + inout_expression env (Pos.same (Com.Var (Pos.unmark m)) m) + let rec inout_instrs (env : var_env) (tmps : Pos.t StrMap.t) (instrs : (int Pos.marked, Mast.error_name) Com.m_instruction list) : Pos.t StrMap.t * Pos.t StrMap.t * Pos.t list StrMap.t = @@ -2178,7 +2258,7 @@ let rec inout_instrs (env : var_env) (tmps : Pos.t StrMap.t) StrMap.add vn def_list def_vars in aux (tmps, in_vars, out_vars, def_vars) il - | TabAccess (_, m_id, m_i) -> + | TabAccess ((_, m_id), m_i) -> let m_v = let var = IntMap.find (Pos.unmark m_id) env.prog.prog_dict @@ -2224,7 +2304,7 @@ let rec inout_instrs (env : var_env) (tmps : Pos.t StrMap.t) in aux (tmps, in_vars, out_vars, def_vars) il | Com.Switch (e, l) -> - let in_expr = inout_expression env e in + let in_expr = inout_switch_expression env e in (* Reversed order, but it does not matter *) let in_l, out_l, def_l = List.fold_left diff --git a/src/mlang/m_ir/com.ml b/src/mlang/m_ir/com.ml index 5e3db3e24..0bc874a1f 100644 --- a/src/mlang/m_ir/com.ml +++ b/src/mlang/m_ir/com.ml @@ -438,8 +438,6 @@ type variable_space = { type literal = Float of float | Undefined -type case = Default | Value of literal - (** Unary operators *) type unop = Not | Minus @@ -477,13 +475,17 @@ type m_var_name = var_name Pos.marked type var_space = (m_var_name * int) option +type 'v var_id = var_space * 'v + type 'v access = - | VarAccess of var_space * 'v - | TabAccess of var_space * 'v * 'v m_expression + | VarAccess of 'v var_id + | TabAccess of 'v var_id * 'v m_expression | FieldAccess of var_space * 'v m_expression * string Pos.marked * int and 'v m_access = 'v access Pos.marked +and 'v case = CDefault | CValue of literal | CVar of 'v m_access + and 'v atom = AtomVar of 'v | AtomLiteral of literal and 'v set_value_loop = @@ -620,6 +622,10 @@ type stop_kind = (* Leave the iterator with the selected var (or the current if [None]) *) +type 'v switch_expression = + | SEValue of 'v m_expression + | SESameVariable of 'v m_access + type ('v, 'e) instruction = | Affectation of 'v formula Pos.marked | IfThenElse of @@ -656,7 +662,8 @@ type ('v, 'e) instruction = * ('v * 'v m_expression) option * 'v m_expression option * ('v, 'e) m_instruction list - | Switch of ('v m_expression * (case list * ('v, 'e) m_instruction list) list) + | Switch of + ('v switch_expression * ('v case list * ('v, 'e) m_instruction list) list) | RaiseError of 'e Pos.marked * string Pos.marked option | CleanErrors | CleanFinalizedErrors @@ -683,10 +690,10 @@ let target_is_function t = t.target_result <> None let rec access_map_var f = function | VarAccess (m_sp_opt, v) -> VarAccess (m_sp_opt, f v) - | TabAccess (m_sp_opt, v, m_i) -> + | TabAccess ((m_sp_opt, v), m_i) -> let v' = f v in let m_i' = m_expr_map_var f m_i in - TabAccess (m_sp_opt, v', m_i') + TabAccess ((m_sp_opt, v'), m_i') | FieldAccess (m_sp_opt, m_i, field, id) -> let m_i' = m_expr_map_var f m_i in FieldAccess (m_sp_opt, m_i', field, id) @@ -802,6 +809,15 @@ and formula_map_var f = function let fd' = formula_decl_map_var f fd in MultipleFormulaes (fl', fd') +and case_map_var f = function + | CDefault -> CDefault + | CValue v -> CValue v + | CVar acc -> CVar (m_access_map_var f acc) + +and switch_expr_map_var f = function + | SEValue e -> SEValue (m_expr_map_var f e) + | SESameVariable m_a -> SESameVariable (m_access_map_var f m_a) + and instr_map_var f g = function | Affectation m_f -> Affectation (Pos.map (formula_map_var f) m_f) | IfThenElse (m_e0, m_il0, m_il1) -> @@ -810,9 +826,12 @@ and instr_map_var f g = function let m_il1' = List.map (m_instr_map_var f g) m_il1 in IfThenElse (m_e0', m_il0', m_il1') | Switch (e, l) -> - let e' = m_expr_map_var f e in + let e' = switch_expr_map_var f e in let l' = - List.map (fun (c, l) -> (c, List.map (m_instr_map_var f g) l)) l + List.map + (fun (c, l) -> + (List.map (case_map_var f) c, List.map (m_instr_map_var f g) l)) + l in Switch (e', l') | WhenDoElse (m_eil, m_il) -> @@ -920,7 +939,7 @@ let fold_opt fold opt acc = match opt with Some e -> fold e acc | None -> acc let rec access_fold_var usage f a acc = match a with | VarAccess (m_sp_opt, v) -> acc |> f usage m_sp_opt (Some v) - | TabAccess (m_sp_opt, v, m_i) -> + | TabAccess ((m_sp_opt, v), m_i) -> acc |> f usage m_sp_opt (Some v) |> m_expr_fold_var f m_i | FieldAccess (m_sp_opt, m_i, _, _) -> acc |> f usage m_sp_opt None |> m_expr_fold_var f m_i @@ -1021,6 +1040,11 @@ and formula_fold_var f fm acc = | MultipleFormulaes (fl, fd) -> acc |> formula_loop_fold_var f fl |> formula_decl_fold_var f fd +and switch_expr_fold_var f se acc = + match se with + | SEValue e -> m_expr_fold_var f e acc + | SESameVariable v -> m_access_fold_var Info f v acc + and instr_fold_var f instr acc = match instr with | Affectation m_f -> formula_fold_var f (Pos.unmark m_f) acc @@ -1029,7 +1053,7 @@ and instr_fold_var f instr acc = |> fold_list (m_instr_fold_var f) m_il0 |> fold_list (m_instr_fold_var f) m_il1 | Switch (e, l) -> - acc |> m_expr_fold_var f e + acc |> switch_expr_fold_var f e |> fold_list (fun (_, l) -> fold_list (m_instr_fold_var f) l) l | WhenDoElse (m_eil, m_il) -> let fold (m_e0, m_il0, _) accu = @@ -1113,10 +1137,6 @@ let format_literal fmt l = Format.pp_print_string fmt (match l with Float f -> string_of_float f | Undefined -> "indefini") -let format_case fmt = function - | Default -> Format.pp_print_string fmt "default" - | Value v -> format_literal fmt v - let format_atom form_var fmt vl = match vl with | AtomVar v -> form_var fmt v @@ -1180,21 +1200,19 @@ let format_comp_op fmt op = | Eq -> "=" | Neq -> "!=") +let format_varid form_var fmt (m_sp_opt, v) = + let sp_str = + match m_sp_opt with + | None -> "" + | Some (m_sp, _) -> get_var_name (Pos.unmark m_sp) ^ "." + in + Pp.fpr fmt "%s%a" sp_str form_var v + let format_access form_var form_expr fmt = function - | VarAccess (m_sp_opt, v) -> - let sp_str = - match m_sp_opt with - | None -> "" - | Some (m_sp, _) -> get_var_name (Pos.unmark m_sp) ^ "." - in - Pp.fpr fmt "%s%a" sp_str form_var v - | TabAccess (m_sp_opt, v, m_i) -> - let sp_str = - match m_sp_opt with - | None -> "" - | Some (m_sp, _) -> get_var_name (Pos.unmark m_sp) ^ "." - in - Pp.fpr fmt "%s%a[%a]" sp_str form_var v form_expr (Pos.unmark m_i) + | VarAccess v_id -> format_varid form_var fmt v_id + | TabAccess (v_id, m_i) -> + Pp.fpr fmt "%a[%a]" (format_varid form_var) v_id form_expr + (Pos.unmark m_i) | FieldAccess (m_sp_opt, e, f, _) -> let sp_str = match m_sp_opt with @@ -1204,6 +1222,11 @@ let format_access form_var form_expr fmt = function Pp.fpr fmt "%schamp_evenement(%a, %s)" sp_str form_expr (Pos.unmark e) (Pos.unmark f) +let format_case form_var form_expr fmt = function + | CDefault -> Format.pp_print_string fmt "default" + | CValue v -> format_literal fmt v + | CVar acc -> format_access form_var form_expr fmt (Pos.unmark acc) + let format_set_value form_var form_expr fmt sv = match sv with | FloatValue i -> Pp.fpr fmt "%f" (Pos.unmark i) @@ -1356,10 +1379,19 @@ let rec format_instruction form_var form_err = Format.fprintf fmt "if(%a):@\n@[ %a@]else:@\n@[ %a@]@\n" form_expr (Pos.unmark cond) form_instrs t form_instrs f | Switch (e, l) -> - Format.fprintf fmt "switch (%a) : (@," form_expr (Pos.unmark e); + Format.fprintf fmt "aiguillage "; + let () = + match e with + | SEValue e -> Format.fprintf fmt "(%a)" form_expr (Pos.unmark e) + | SESameVariable v -> + Format.fprintf fmt "nom (%a)" form_access (Pos.unmark v) + in + Format.fprintf fmt " : (@,"; List.iter (fun (cl, l) -> - List.iter (Format.fprintf fmt "%a :@," format_case) cl; + List.iter + (Format.fprintf fmt "%a :@," (format_case form_var form_expr)) + cl; Format.fprintf fmt "@[ %a@]" form_instrs l) l; Format.fprintf fmt "@]@," diff --git a/src/mlang/m_ir/com.mli b/src/mlang/m_ir/com.mli index 25ba1f587..debe14b06 100644 --- a/src/mlang/m_ir/com.mli +++ b/src/mlang/m_ir/com.mli @@ -218,8 +218,6 @@ type verif_domain = verif_domain_data domain type literal = Float of float | Undefined -type case = Default | Value of literal - (** Unary operators *) type unop = Not | Minus @@ -268,13 +266,17 @@ type m_var_name = var_name Pos.marked type var_space = (m_var_name * int) option +type 'v var_id = var_space * 'v + type 'v access = - | VarAccess of var_space * 'v - | TabAccess of var_space * 'v * 'v m_expression + | VarAccess of 'v var_id + | TabAccess of 'v var_id * 'v m_expression | FieldAccess of var_space * 'v m_expression * string Pos.marked * int and 'v m_access = 'v access Pos.marked +and 'v case = CDefault | CValue of literal | CVar of 'v m_access + (** Values that can be substituted for loop parameters *) and 'v atom = AtomVar of 'v | AtomLiteral of literal @@ -386,6 +388,10 @@ type stop_kind = (* Leave the iterator with the selected var (or the current if [None]) *) +type 'v switch_expression = + | SEValue of 'v m_expression + | SESameVariable of 'v m_access + type ('v, 'e) instruction = | Affectation of 'v formula Pos.marked | IfThenElse of @@ -422,7 +428,8 @@ type ('v, 'e) instruction = * ('v * 'v m_expression) option * 'v m_expression option * ('v, 'e) m_instruction list - | Switch of ('v m_expression * (case list * ('v, 'e) m_instruction list) list) + | Switch of + ('v switch_expression * ('v case list * ('v, 'e) m_instruction list) list) | RaiseError of 'e Pos.marked * string Pos.marked option | CleanErrors | CleanFinalizedErrors @@ -488,7 +495,12 @@ val format_value_typ : Pp.t -> value_typ -> unit val format_literal : Pp.t -> literal -> unit -val format_case : Pp.t -> case -> unit +val format_case : + (Pp.t -> 'v -> unit) -> + (Pp.t -> 'v expression -> unit) -> + Pp.t -> + 'v case -> + unit val format_atom : (Pp.t -> 'v -> unit) -> Pp.t -> 'v atom -> unit diff --git a/src/mlang/m_ir/mir.ml b/src/mlang/m_ir/mir.ml index d1c6c5049..042b25372 100644 --- a/src/mlang/m_ir/mir.ml +++ b/src/mlang/m_ir/mir.ml @@ -240,9 +240,9 @@ and expand_functions_access (p : program) (access : 'var Com.access) : 'var Com.access = match access with | VarAccess _ -> access - | TabAccess (m_sp_opt, m_v, i) -> + | TabAccess ((m_sp_opt, m_v), i) -> let i' = expand_functions_expr p i in - TabAccess (m_sp_opt, m_v, i') + TabAccess ((m_sp_opt, m_v), i') | FieldAccess (m_sp_opt, v_i, f, i_f) -> let m_i = expand_functions_expr p v_i in FieldAccess (m_sp_opt, m_i, f, i_f) @@ -356,7 +356,11 @@ let expand_functions (p : program) : program = let instrs' = List.map map_instr instrs in Pos.same (ArrangeEvents (sort', filter', add', instrs')) m_instr | Switch (e, l) -> - let e' = expand_functions_expr p e in + let e' = + match e with + | Com.SEValue e -> SEValue (expand_functions_expr p e) + | Com.SESameVariable v -> SESameVariable v + in let l' = List.map (fun (c, l) -> (c, List.map map_instr l)) l in Pos.same (Switch (e', l')) m_instr | RaiseError _ | CleanErrors | CleanFinalizedErrors | ExportErrors diff --git a/src/mlang/m_ir/mir_interpreter.ml b/src/mlang/m_ir/mir_interpreter.ml index 26aa03eb5..648f7c651 100644 --- a/src/mlang/m_ir/mir_interpreter.ml +++ b/src/mlang/m_ir/mir_interpreter.ml @@ -430,7 +430,7 @@ struct | Com.VarAccess (m_sp_opt, v) -> let vsd_opt = get_var_space_from ctx m_sp_opt in get_var_value ctx vsd_opt v - | Com.TabAccess (m_sp_opt, m_v, m_idx) -> ( + | Com.TabAccess ((m_sp_opt, m_v), m_idx) -> ( match evaluate_expr ctx m_idx with | Number z -> let vsd_opt = get_var_space_from ctx m_sp_opt in @@ -467,7 +467,7 @@ struct let vsd_opt = get_var_space_from ctx m_sp_opt in let vsd, v, _ = get_var ctx vsd_opt v in Some (vsd, v) - | Com.TabAccess (m_sp_opt, m_v, m_i) -> ( + | Com.TabAccess ((m_sp_opt, m_v), m_i) -> ( match evaluate_expr ctx m_i with | Number z -> let vsd_opt = get_var_space_from ctx m_sp_opt in @@ -526,6 +526,14 @@ struct | Some (vsd, v) -> set_var_value ctx (Some vsd) v @@ evaluate_expr ctx vexpr | None -> () + and evaluate_switch_expr (ctx : ctx) s_e = + match s_e with + | Com.SEValue e -> ( + match evaluate_expr ctx e with + | Undefined -> `Undefined + | Number n -> `Value n) + | SESameVariable v -> `Var v + and evaluate_expr (ctx : ctx) (e : Mir.expression Pos.marked) : value = let comparison op new_e1 new_e2 = match (op, new_e1, new_e2) with @@ -679,7 +687,7 @@ struct let vn = Com.Normal (Pos.unmark vsd.vs_name) in Some (Pos.without vn, vsd.vs_id) in - let a = Com.TabAccess (m_sp_opt, var_arg2, ei) in + let a = Com.TabAccess ((m_sp_opt, var_arg2), ei) in Pos.same (Com.Var a) arg2 in cast_to_int @@ evaluate_expr ctx instr @@ -726,23 +734,9 @@ struct then Number (N.one ()) else Number (N.zero ()) | None -> Undefined) - | SameVariable (m_acc0, m_acc1) -> ( - match get_access_var ctx (Pos.unmark m_acc0) with - | Some (vsd0, v0) -> ( - let _, v0', _ = get_var ctx (Some vsd0) v0 in - match get_access_var ctx (Pos.unmark m_acc1) with - | Some (vsd1, v1) -> ( - let _, v1', _ = get_var ctx (Some vsd1) v1 in - if Com.Var.name_str v0' = Com.Var.name_str v1' then - Number (N.one ()) - else - match (Com.Var.alias v0', Com.Var.alias v1') with - | Some m_a0, Some m_a1 - when Pos.unmark m_a0 = Pos.unmark m_a1 -> - Number (N.one ()) - | _ -> Number (N.zero ())) - | None -> Number (N.zero ())) - | None -> Number (N.zero ())) + | SameVariable (m_acc0, m_acc1) -> + if same_variable ctx m_acc0 m_acc1 then Number (N.one ()) + else Number (N.zero ()) | InDomain (m_acc, cvm) -> ( match get_access_var ctx (Pos.unmark m_acc) with | Some (vsd, v) -> @@ -782,6 +776,22 @@ struct else raise (RuntimeError (e, ctx)) else out + and same_variable ctx m_acc m_acc' : bool = + match get_access_var ctx (Pos.unmark m_acc) with + | Some (vsd0, v0) -> ( + let _, v0', _ = get_var ctx (Some vsd0) v0 in + match get_access_var ctx (Pos.unmark m_acc') with + | Some (vsd1, v1) -> ( + let _, v1', _ = get_var ctx (Some vsd1) v1 in + if Com.Var.name_str v0' = Com.Var.name_str v1' then true + else + match (Com.Var.alias v0', Com.Var.alias v1') with + | Some m_a0, Some m_a1 when Pos.unmark m_a0 = Pos.unmark m_a1 -> + true + | _ -> false) + | None -> false) + | None -> false + and evaluate_stmt (canBlock : bool) (ctx : ctx) (stmt : Mir.m_instruction) : unit = match Pos.unmark stmt with @@ -805,21 +815,32 @@ struct | Number _ -> evaluate_stmts canBlock ctx t | Undefined -> ()) | Com.Switch (c, l) -> ( - let v = evaluate_expr ctx c in let exception INTERNAL_STOP_SWITCH in let then_ () = raise INTERNAL_STOP_SWITCH in + let v = evaluate_switch_expr ctx c in + let default = ref None in try List.iter (fun (cases, stmts) -> List.iter (fun case -> match (case, v) with - | Com.Default, _ | Value Undefined, Undefined -> - evaluate_stmts ~then_ canBlock ctx stmts - | Value (Float f), Number n - when compare_numbers Eq n (N.of_float f) -> + | Com.CDefault, _ -> + (* Trigged only if all other cases fail *) + default := Some stmts + | CValue Undefined, `Undefined -> evaluate_stmts ~then_ canBlock ctx stmts - | _ -> ()) + | CValue _, `Undefined | CValue Undefined, _ -> () + | CValue (Float f), `Value v -> + if N.of_float f = v then + evaluate_stmts ~then_ canBlock ctx stmts + | CValue _, `Var _ -> + failwith "Cannot match value with variable" + | CVar m_acc, `Var v -> + if same_variable ctx m_acc v then + evaluate_stmts ~then_ canBlock ctx stmts + | CVar _, (`Value _ | `Undefined) -> + failwith "Cannot match variable with value") cases) l with INTERNAL_STOP_SWITCH -> ())