Skip to content

Warnings on unused and undefined variables #260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions remove_unused_variables.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/sh

set -ue

if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
echo "Usage: $0 <file containing names of variables to be removed> <directory of the code base> \
<name of the file that will contain the SQL queries>"
exit 1
fi

var_file="$1"
code_base="$2"
sql_file="$3"

if [ ! -f "$var_file" ]; then
echo "The file $var_file does not exist"
exit 2
fi
if [ -f "$sql_file" ] && [ ! -s "$sql_file" ]; then
echo "The file $sql_file exists and is not empty"
exit 3
fi

counter=0

while IFS= read -r var; do
if [ -z "$var" ]; then
continue
fi

echo "Processing variable $var"

grep -lE "^${var}[^(A-Z|a-z|0-9|_)]" "$code_base/*.m" | while IFS= read -r file
do
awk "/^$var([^a-zA-Z0-9_]|$)/ {f=1} f {if (/;/) {f=0} next} 1" "$file" > temp && mv temp "$file"
done

# La ligne suivante suppose une modification des makefiles pour tester sur une version en cours de développement de Mlang
YEAR=2024 TEST_FILE=tests/dummy.irj make test
counter=$((counter + 1)) && echo $counter
echo "delete from dico_24 where variable='$var';" >> "$sql_file"
done < "$var_file"

echo "Done"
1 change: 1 addition & 0 deletions src/mlang/driver.ml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ let driver (files : string list) (application_names : string list)
Cli.debug_print "Elaborating...";
let m_program = Mast_to_mir.translate !m_program mpp_function in
let m_program = Mir.expand_functions m_program in
Mir_collect.warn_unused_variables m_program.program_targets;
Cli.debug_print "Creating combined program suitable for execution...";
if run_all_tests <> None then
let tests : string =
Expand Down
2 changes: 1 addition & 1 deletion src/mlang/dune
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
(library
(public_name mlang)
(libraries re ANSITerminal parmap cmdliner threads dune-build-info num gmp
menhirLib))
ocamlgraph menhirLib))

(documentation
(package mlang)
Expand Down
61 changes: 60 additions & 1 deletion src/mlang/m_frontend/check_validity.ml
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@ let check_var_decl (var_decl : Mast.variable_decl) (prog : program) : program =
~attrs:(get_attributes input_var.Mast.input_attributes)
~cat:global_category
~typ:(Option.map Pos.unmark input_var.Mast.input_typ)
~in_verif:false
in
check_global_var var prog
| Mast.ComputedVar (comp_var, _decl_pos) ->
Expand All @@ -699,6 +700,7 @@ let check_var_decl (var_decl : Mast.variable_decl) (prog : program) : program =
~attrs:(get_attributes comp_var.Mast.comp_attributes)
~cat:global_category
~typ:(Option.map Pos.unmark comp_var.Mast.comp_typ)
~in_verif:false
in
check_global_var var prog

Expand Down Expand Up @@ -828,6 +830,36 @@ let check_verif_dom_decl (decl : Mast.verif_domain_decl) (prog : program) :
let doms, syms = check_domain Verif decl dom_data doms_syms in
{ prog with prog_vdoms = doms; prog_vdom_syms = syms }

let warn_on_undef_computed_vars (rules : rule IntMap.t)
(vars : Com.Var.t StrMap.t) =
let def_vars =
IntMap.fold
(fun _ rule set ->
List.fold_left
(fun set m_instr ->
let instr = Pos.unmark m_instr in
match instr with
| Com.Affectation m_formula -> begin
let formula = Pos.unmark m_formula in
match formula with
| Com.SingleFormula (var, _, _) ->
StrSet.add (Mast.get_variable_name (Pos.unmark var)) set
| Com.MultipleFormulaes _ -> assert false
end
| _ -> set)
set rule.rule_instrs)
rules StrSet.empty
in
StrMap.iter
(fun var_name var ->
match Com.Var.cat var with
| Computed _ ->
if not (StrSet.mem var_name def_vars) then
Cli.warning_print
"Variable %s is declared as computed but never defined" var_name
| Input _ -> ())
vars

let complete_vars (prog : program) : program =
let prog_vars = prog.prog_vars in
let prog_vars =
Expand Down Expand Up @@ -1058,6 +1090,7 @@ let complete_vars (prog : program) : program =
sz_all_tmps;
}
in
warn_on_undef_computed_vars prog.prog_rules prog_vars;
{ prog with prog_vars; prog_targets; prog_stats }

let complete_dom_decls (rov : rule_or_verif) ((doms, syms) : 'a doms * syms) :
Expand Down Expand Up @@ -2363,6 +2396,32 @@ let convert_verifs (prog : program) : program =
in
{ prog with prog_targets }

let add_verif_info (v : verif) (prog : program) : program =
let used_vars = Com.get_used_variables (Pos.unmark v.verif_expr) in
let prog_vars =
List.fold_left
(fun vars var ->
let vn =
match var with
| Mast.Normal var_name -> var_name
| Mast.Generic _ -> assert false
in
let var = StrMap.find vn vars in
let var =
match var.Com.Var.scope with
| Tgv tgv -> { var with scope = Tgv { tgv with in_verif = true } }
| _ -> var
in
StrMap.add vn var vars)
prog.prog_vars used_vars
in
{ prog with prog_vars }

let add_verif_info_all_vars (prog : program) : program =
IntMap.fold
(fun _ verif prog -> add_verif_info verif prog)
prog.prog_verifs prog

let eval_expr_verif (prog : program) (verif : verif)
(expr : Mast.expression Pos.marked) : float option =
let my_floor a = floor (a +. 0.000001) in
Expand Down Expand Up @@ -2671,4 +2730,4 @@ let proceed (p : Mast.program) (main_target : string) : program =
in
prog |> complete_rdom_decls |> complete_vdom_decls |> convert_rules
|> complete_rule_domains |> complete_chainings |> convert_verifs
|> complete_verif_calls |> complete_vars
|> add_verif_info_all_vars |> complete_verif_calls |> complete_vars
58 changes: 55 additions & 3 deletions src/mlang/m_ir/com.ml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ module Var = struct
cat : CatVar.t;
is_given_back : bool;
typ : value_typ option;
in_verif : bool;
}

type scope = Tgv of tgv | Temp of int option | Ref | Arg | Res
Expand All @@ -142,6 +143,8 @@ module Var = struct
Errors.raise_error
(Format.sprintf "%s is not a TGV variable" (Pos.unmark v.name))

let tgv_opt v = match v.scope with Tgv s -> Some s | _ -> None

let name v = v.name

let name_str v = Pos.unmark v.name
Expand Down Expand Up @@ -175,7 +178,15 @@ module Var = struct

let cat v = (tgv v).cat

let is_given_back v = (tgv v).is_given_back
let is_given_back v =
match tgv_opt v with Some s -> s.is_given_back | None -> false

let is_base v =
match tgv_opt v with
| Some s when s.cat = Computed { is_base = true } -> true
| _ -> false

let in_verif v = (tgv v).in_verif

let loc_tgv v =
match v.loc with
Expand Down Expand Up @@ -214,12 +225,23 @@ module Var = struct
let new_tgv ~(name : string Pos.marked) ~(is_table : int option)
~(is_given_back : bool) ~(alias : string Pos.marked option)
~(descr : string Pos.marked) ~(attrs : int Pos.marked StrMap.t)
~(cat : CatVar.t) ~(typ : value_typ option) : t =
~(cat : CatVar.t) ~(typ : value_typ option) ~(in_verif : bool) : t =
{
name;
id = new_id ();
loc = LocTgv (Pos.unmark name, init_loc cat);
scope = Tgv { is_table; alias; descr; attrs; cat; is_given_back; typ };
scope =
Tgv
{
is_table;
alias;
descr;
attrs;
cat;
is_given_back;
typ;
in_verif : bool;
};
}

let new_temp ~(name : string Pos.marked) ~(is_table : int option)
Expand Down Expand Up @@ -411,6 +433,36 @@ type 'v expression =

and 'v m_expression = 'v expression Pos.marked

let get_used_variables (e : 'v expression) : 'v list =
let rec get_used_variables_ (e : 'v expression) (acc : 'v list) =
match e with
| TestInSet (_, (e, _), _) | Unop (_, (e, _)) ->
let acc = get_used_variables_ e acc in
acc
| Comparison (_, (e1, _), (e2, _)) | Binop (_, (e1, _), (e2, _)) ->
let acc = get_used_variables_ e1 acc in
let acc = get_used_variables_ e2 acc in
acc
| Index ((var, _), (e, _)) ->
let acc = var :: acc in
let acc = get_used_variables_ e acc in
acc
| Conditional ((e1, _), (e2, _), e3) -> (
let acc = get_used_variables_ e1 acc in
let acc = get_used_variables_ e2 acc in
match e3 with None -> acc | Some (e3, _) -> get_used_variables_ e3 acc)
| FuncCall (_, args) ->
List.fold_left
(fun acc (arg, _) -> get_used_variables_ arg acc)
acc args
| FuncCallLoop _ | Loop _ -> assert false
| Var var | Size (var, _) | Attribut ((var, _), _) -> var :: acc
| Literal _ | NbCategory _ | NbAnomalies | NbDiscordances | NbInformatives
| NbBloquantes ->
acc
in
get_used_variables_ e []

module Error = struct
type typ = Anomaly | Discordance | Information

Expand Down
8 changes: 8 additions & 0 deletions src/mlang/m_ir/com.mli
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ module Var : sig
cat : CatVar.t;
is_given_back : bool;
typ : value_typ option;
in_verif : bool;
}

type scope = Tgv of tgv | Temp of int option | Ref | Arg | Res
Expand Down Expand Up @@ -101,6 +102,10 @@ module Var : sig

val is_given_back : t -> bool

val is_base : t -> bool

val in_verif : t -> bool

val loc_tgv : t -> loc_tgv

val loc_int : t -> int
Expand All @@ -124,6 +129,7 @@ module Var : sig
attrs:int Pos.marked StrMap.t ->
cat:CatVar.t ->
typ:value_typ option ->
in_verif:bool ->
t

val new_temp :
Expand Down Expand Up @@ -267,6 +273,8 @@ type 'v expression =

and 'v m_expression = 'v expression Pos.marked

val get_used_variables : 'v expression -> 'v list

module Error : sig
type typ = Anomaly | Discordance | Information

Expand Down
Loading