Commit 18b2e34c authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Check fully boolean decision branches

parent d9967b59
...@@ -3496,7 +3496,7 @@ def decision(root, parent, context): ...@@ -3496,7 +3496,7 @@ def decision(root, parent, context):
covered_ranges[ans].append(ans.inputString) covered_ranges[ans].append(ans.inputString)
is_enum = True is_enum = True
elif q_basic.kind == 'BooleanType': elif q_basic.kind == 'BooleanType':
covered_ranges[ans].append(ans.inputString) covered_ranges[ans].append(ans.constant.value[0])
is_bool = True is_bool = True
if not ans.constant.is_raw: if not ans.constant.is_raw:
need_else = True need_else = True
...@@ -3633,8 +3633,10 @@ def decision(root, parent, context): ...@@ -3633,8 +3633,10 @@ def decision(root, parent, context):
# (2) no gap in the coverage of the decision possible values # (2) no gap in the coverage of the decision possible values
# (3) ELSE branch, if present, can be reached # (3) ELSE branch, if present, can be reached
# (4) if an answer uses a non-ground expression an ELSE is there # (4) if an answer uses a non-ground expression an ELSE is there
# (5) present() operator and enumerated question are fully covered # (5) boolean expressions are fully covered
# (6) present() operator and enumerated question are fully covered
# (1) no overlap between covered ranges in decision answers
q_ranges = [(qmin, qmax)] if dec.question \ q_ranges = [(qmin, qmax)] if dec.question \
and is_numeric(dec.question.exprType) else [] and is_numeric(dec.question.exprType) else []
for each in combinations(covered_ranges.viewitems(), 2): for each in combinations(covered_ranges.viewitems(), 2):
...@@ -3690,7 +3692,14 @@ def decision(root, parent, context): ...@@ -3690,7 +3692,14 @@ def decision(root, parent, context):
qwarn.append('Decision "{}": Missing ELSE branch' qwarn.append('Decision "{}": Missing ELSE branch'
.format(dec.inputString)) .format(dec.inputString))
# (5) check coverage of enumerated types # (5) check coverage of boolean types
# Rules:
# a. exactly 2 answers
# b. if one answer is not ground expression, other branch must be ELSE
# c. if there is a ground expression G in a branch, the other branch
# must evaluate to non-G or be ELSE
# (6) check coverage of enumerated types
if is_enum or is_bool: if is_enum or is_bool:
# check duplicate answers # check duplicate answers
answers = [a.lower() answers = [a.lower()
...@@ -3700,11 +3709,13 @@ def decision(root, parent, context): ...@@ -3700,11 +3709,13 @@ def decision(root, parent, context):
qerr.append('Decision "{}": duplicate answers "{}"' qerr.append('Decision "{}": duplicate answers "{}"'
.format(dec.inputString, '", "'.join(dupl))) .format(dec.inputString, '", "'.join(dupl)))
if is_bool: if is_bool:
# Boolean special case: values are just True and False
enumerants = ['true', 'false'] enumerants = ['true', 'false']
if len(answers) + (1 if has_else else 0) != 2:
qerr.append('Boolean decision "{}" must have exactly 2 answers'
.format(dec.inputString))
else: else:
enumerants = [en.replace('-', '_').lower() enumerants = [en.replace('-', '_').lower()
for en in q_basic.EnumValues.keys()] for en in q_basic.EnumValues.keys()]
# check for missing answers # check for missing answers
if set(answers) != set(enumerants) and not has_else: if set(answers) != set(enumerants) and not has_else:
qerr.append('Decision "{}": Missing branches for answer(s) "{}"' qerr.append('Decision "{}": Missing branches for answer(s) "{}"'
......
[ERROR] Decision "var6": No answer to cover range -5.0 .. 10.0 [ERROR] Boolean decision "varbool" must have exactly 2 answers
[ERROR] Decision "var6": answers >=10.0 and <=10.0 are overlapping in range 10.0 .. 10.0
[ERROR] Decision "var6": No answer to cover range 0.0 .. 0.1 [ERROR] Decision "var6": No answer to cover range 0.0 .. 0.1
[ERROR] Decision "var6": No answer to cover range 10.0 .. 10.5 [ERROR] Decision "var6": No answer to cover range 10.0 .. 10.5
[ERROR] Decision "var6": No answer to cover range -5.0 .. 10.0
[ERROR] Decision "var6": No answer to cover value 10.0 [ERROR] Decision "var6": No answer to cover value 10.0
[ERROR] Decision "var6": answers >=10.0 and <=10.0 are overlapping in range 10.0 .. 10.0
[ERROR] Decision "varbool": Missing branches for answer(s) "false" [ERROR] Decision "varbool": Missing branches for answer(s) "false"
[ERROR] Decision "varbool": Missing branches for answer(s) "false" [ERROR] Decision "varbool": Missing branches for answer(s) "false"
[ERROR] Too many errors, cannot generate code [ERROR] Too many errors, cannot generate code
[INFO] Checking ['myfunction.pr', 'system_structure.pr'] [INFO] Checking ['myfunction.pr', 'system_structure.pr']
[INFO] Parsing complete. Summary, found 3 warnings and 7 errors
[INFO] myfunction.pr [INFO] myfunction.pr
[WARNING] Decision "var6": Range -10.0 .. -5.0 is unreachable [INFO] Parsing complete. Summary, found 3 warnings and 8 errors
[WARNING] Decision "var6": Range 100.0 .. 150.0 is unreachable [WARNING] Decision "var6": Range 100.0 .. 150.0 is unreachable
[WARNING] Decision "var6": Range -10.0 .. -5.0 is unreachable
[WARNING] Decision "varbool": Missing ELSE branch [WARNING] Decision "varbool": Missing ELSE branch
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment