Commit 75d7a427 authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Added detection of expressions that are always true or always false

parent 34788ab2
......@@ -858,7 +858,7 @@ def fix_expression_types(expr, context):
except AttributeError:
pass
# If a side of the expression is of Enumerated of Choice type, check if
# If a side of the expression is of Enumerated or Choice type, check if
# the other side is a literal of that sort, and change type accordingly
for side in permutations(('left', 'right')):
side_type = find_basic_type(getattr(expr, side[0]).exprType).kind
......@@ -888,6 +888,28 @@ def fix_expression_types(expr, context):
typed_expr = side
ref_type = typed_expr.exprType
# If a side is a raw Sequence Of with unknown type, try to resolve it
for side in permutations(('left', 'right')):
value = getattr(expr, side[0]) # get expr.left then expr.right
if not isinstance(value, ogAST.PrimSequenceOf):
continue
other = getattr(expr, side[1]) # other side
basic = find_basic_type(value.exprType)
if basic.kind == 'SequenceOfType' and basic.type == UNKNOWN_TYPE:
asn_type = find_basic_type(other.exprType)
if asn_type.kind == 'SequenceOfType':
asn_type = asn_type.type
for idx, elem in enumerate(value.value):
check_expr = ogAST.ExprAssign()
check_expr.left = ogAST.PrimPath()
check_expr.left.exprType = asn_type
check_expr.right = elem
fix_expression_types(check_expr, context)
value.value[idx] = check_expr.right
# the type of the raw PrimSequenceOf can be set now
value.exprType.type = asn_type
# Type check that is specific to IN expressions
if isinstance(expr, ogAST.ExprIn):
# check that left part is a SEQUENCE OF or a string
......@@ -899,6 +921,20 @@ def fix_expression_types(expr, context):
else:
raise TypeError('IN expression: right part must be a list')
compare_types(expr.right.exprType, ref_type)
if expr.right.is_raw == expr.left.is_raw == True:
# If both sides are raw (e.g. "3 in {1,2,3}"), evaluate expression
bool_expr = ogAST.PrimBoolean()
bool_expr.inputString = expr.inputString
bool_expr.line = expr.line
bool_expr.charPositionInLine = expr.charPositionInLine
bool_expr.exprType = type('PrBool', (object,),
{'kind': 'BooleanType'})
if expr.right.value in [each.value for each in expr.left.value]:
bool_expr.value = ['true']
raise Warning('Expression is always true', bool_expr)
else:
bool_expr.value = ['false']
raise Warning('Expression is always false', bool_expr)
return
if expr.right.is_raw == expr.left.is_raw == False:
......@@ -959,17 +995,17 @@ def fix_expression_types(expr, context):
check_expr.right = expr.right.value[det]
fix_expression_types(check_expr, context)
expr.right.value[det] = check_expr.right
elif isinstance(expr.right, ogAST.PrimSequenceOf):
asn_type = find_basic_type(expr.left.exprType).type
for idx, elem in enumerate(expr.right.value):
check_expr = ogAST.ExprAssign()
check_expr.left = ogAST.PrimPath()
check_expr.left.exprType = asn_type
check_expr.right = elem
fix_expression_types(check_expr, context)
expr.right.value[idx] = check_expr.right
# the type of the raw PrimSequenceOf can be set now
expr.right.exprType.type = asn_type
# elif isinstance(expr.right, ogAST.PrimSequenceOf):
# asn_type = find_basic_type(expr.left.exprType).type
# for idx, elem in enumerate(expr.right.value):
# check_expr = ogAST.ExprAssign()
# check_expr.left = ogAST.PrimPath()
# check_expr.left.exprType = asn_type
# check_expr.right = elem
# fix_expression_types(check_expr, context)
# expr.right.value[idx] = check_expr.right
# # the type of the raw PrimSequenceOf can be set now
# expr.right.exprType.type = asn_type
if isinstance(expr, (ogAST.ExprAnd, ogAST.ExprOr, ogAST.ExprXor)):
# Bitwise operators: check that both sides are booleans
......@@ -1105,8 +1141,12 @@ def primary_value(root, context=None):
prim_elem.line = elem.getLine()
prim_elem.charPositionInLine = elem.getCharPositionInLine()
prim.value.append(prim_elem)
prim.exprType = type('PrSO', (object,), {'kind': 'SequenceOfType',
'Min': str(len(child.children)), 'Max': str(len(child.children))})
prim.exprType = type('PrSO', (object,), {
'kind': 'SequenceOfType',
'Min': str(len(child.children)),
'Max': str(len(child.children)),
'type': UNKNOWN_TYPE
})
elif child.type == lexer.BITSTR:
prim = ogAST.PrimBitStringLiteral()
warnings.append('Bit string literal not supported yet')
......@@ -1282,6 +1322,13 @@ def expression(root, context):
type_name(expr.left.exprType) + '), right (' +
expr.right.inputString + ', type= ' +
type_name(expr.right.exprType) + ') ' + str(err))
except Warning as warn:
# warnings are raised when an expression returns always true or
# false. In that case a new expression is returned
report, new_expr = warn.args
warnings.append('Expression "{}" : {}'.
format(expr.inputString, str(report)))
expr = new_expr
if root.type in (lexer.EQ,
lexer.NEQ,
......@@ -1927,6 +1974,8 @@ def signal(root):
except ValueError:
errors.append(new_signal['name'] + ' cannot have more' +
' than one parameter. Check signal declaration.')
except TypeError as err:
errors.append(str(err))
return new_signal, errors, warnings
......
/* CIF PROCESS (150, 150), (150, 75) */
PROCESS og;
/* CIF TEXT (-679, -140), (298, 286) */
-- A Demo to test octet strings
/* CIF TEXT (-679, -140), (298, 286) */
-- A Demo to test octet strings
-- using various symbols.
-- check that types are case insensitive
......@@ -10,158 +10,171 @@ DCL first_msg, msg my_octStr;
DCL seq SeqOf;
DCL test Some_Thing;
dcl foo MyInteger := 3;
-- Unicode comments: héhé hôhÖ
/* CIF ENDTEXT */
/* CIF START (-252, -114), (100, 50) */
START;
/* CIF TASK (-284, -49), (164, 53) */
TASK test := 5,
dcl alwaysTrue Type2 := 3 in {1,2,3};
dcl alwaysFalse Type2 := 0 in {1,2,3};
/* CIF ENDTEXT */
/* CIF START (-252, -114), (100, 50) */
START;
/* CIF TASK (-284, -49), (164, 53) */
TASK test := 5,
test := abs(-4+1),
test := abs(test)
/* CIF COMMENT (-100, -40), (183, 35) */
COMMENT 'Task with unicode: voilà!';
/* CIF TASK (-304, 19), (204, 50) */
TASK first_msg := 'Say hello first!'
/* CIF COMMENT (-80, 19), (148, 50) */
COMMENT 'String assignment';
/* CIF TASK (-284, 84), (165, 50) */
TASK seq := default_seqof,
/* CIF COMMENT (-100, -40), (183, 35) */
COMMENT 'Task with unicode: voilà!';
/* CIF TASK (-304, 19), (204, 50) */
TASK first_msg := 'Say hello first!'
/* CIF COMMENT (-80, 19), (148, 50) */
COMMENT 'String assignment';
/* CIF TASK (-284, 84), (165, 50) */
TASK seq := default_seqof,
seq := {1,2,3}
/* CIF COMMENT (-100, 84), (204, 50) */
COMMENT 'default_seqof is a constant
/* CIF COMMENT (-100, 84), (204, 50) */
COMMENT 'default_seqof is a constant
defined in the ASN.1 model';
/* CIF TASK (-333, 149), (263, 50) */
TASK seq := seq // {4, test} // default_seqof
/* CIF COMMENT (-50, 149), (156, 50) */
COMMENT 'Concatenate
/* CIF TASK (-333, 149), (263, 50) */
TASK seq := seq // {4, test} // default_seqof
/* CIF COMMENT (-50, 149), (156, 50) */
COMMENT 'Concatenate
two SEQUENCE OF';
/* CIF TASK (-270, 214), (137, 50) */
TASK 'seq(1) := seq(2)';
/* CIF TASK (-298, 279), (193, 50) */
TASK seq := seq(1,2) // seq(4,5)
/* CIF COMMENT (-86, 279), (166, 50) */
COMMENT 'Remove 3rd element';
/* CIF DECISION (-254, 344), (104, 70) */
DECISION test in seq
/* CIF COMMENT (-130, 359), (170, 39) */
COMMENT 'Test the "in" operator
/* CIF TASK (-270, 214), (137, 50) */
TASK 'seq(1) := seq(2)';
/* CIF TASK (-298, 279), (193, 50) */
TASK seq := seq(1,2) // seq(4,5)
/* CIF COMMENT (-86, 279), (166, 50) */
COMMENT 'Remove 3rd element';
/* CIF DECISION (-254, 344), (104, 70) */
DECISION test in seq
/* CIF COMMENT (-130, 359), (170, 39) */
COMMENT 'Test the "in" operator
Unicode test: Ï';
/* CIF ANSWER (-344, 434), (100, 35) */
(TRUE):
/* CIF PROCEDURECALL (-371, 484), (154, 50) */
CALL writeln('All OK (1)');
/* CIF ANSWER (-181, 434), (100, 35) */
(FALSE):
/* CIF PROCEDURECALL (-213, 484), (164, 50) */
CALL writeln('NOT OK (1)')
/* CIF COMMENT (-29, 491), (117, 35) */
COMMENT 'Call UnicÔDË';
ENDDECISION;
/* CIF DECISION (-252, 549), (100, 70) */
DECISION 3 in seq;
/* CIF ANSWER (-338, 639), (100, 35) */
(TRUE):
/* CIF PROCEDURECALL (-370, 689), (164, 50) */
CALL writeln('NOT OK (2)');
/* CIF ANSWER (-166, 639), (100, 35) */
(FALSE):
/* CIF PROCEDURECALL (-196, 689), (161, 50) */
CALL writeln('All OK (2)');
ENDDECISION;
/* CIF NEXTSTATE (-252, 754), (100, 50) */
NEXTSTATE Wait;
/* CIF STATE (420, 11), (100, 50) */
STATE Running;
/* CIF INPUT (420, 81), (100, 50) */
INPUT go(msg);
/* CIF DECISION (418, 146), (103, 70) */
DECISION msg
/* CIF COMMENT (542, 156), (111, 50) */
COMMENT 'Switch-case
/* CIF ANSWER (-344, 434), (100, 35) */
(TRUE):
/* CIF PROCEDURECALL (-371, 484), (154, 50) */
CALL writeln('All OK (1)');
/* CIF ANSWER (-181, 434), (100, 35) */
(FALSE):
/* CIF PROCEDURECALL (-213, 484), (164, 50) */
CALL writeln('NOT OK (1)')
/* CIF COMMENT (-29, 491), (117, 35) */
COMMENT 'Call UnicÔDË';
ENDDECISION;
/* CIF DECISION (-252, 549), (100, 70) */
DECISION 3 in seq;
/* CIF ANSWER (-338, 639), (100, 35) */
(TRUE):
/* CIF PROCEDURECALL (-370, 689), (164, 50) */
CALL writeln('NOT OK (2)');
/* CIF ANSWER (-166, 639), (100, 35) */
(FALSE):
/* CIF PROCEDURECALL (-196, 689), (161, 50) */
CALL writeln('All OK (2)');
ENDDECISION;
/* CIF NEXTSTATE (-252, 754), (100, 50) */
NEXTSTATE Wait;
/* CIF STATE (420, 11), (100, 50) */
STATE Running;
/* CIF INPUT (420, 81), (100, 50) */
INPUT go(msg);
/* CIF DECISION (418, 146), (103, 70) */
DECISION msg
/* CIF COMMENT (542, 156), (111, 50) */
COMMENT 'Switch-case
on strings';
/* CIF ANSWER (670, 236), (100, 35) */
('egg'):
/* CIF TASK (649, 286), (141, 50) */
TASK msg := msg // '!!'
/* CIF COMMENT (811, 286), (118, 50) */
COMMENT 'Concatenate
/* CIF ANSWER (670, 236), (100, 35) */
('egg'):
/* CIF TASK (649, 286), (141, 50) */
TASK msg := msg // '!!'
/* CIF COMMENT (811, 286), (118, 50) */
COMMENT 'Concatenate
strings';
/* CIF OUTPUT (645, 351), (150, 50) */
OUTPUT rezult(default_str)
/* CIF COMMENT (810, 349), (161, 53) */
COMMENT 'Send a constant
/* CIF OUTPUT (645, 351), (150, 50) */
OUTPUT rezult(default_str)
/* CIF COMMENT (810, 349), (161, 53) */
COMMENT 'Send a constant
defined in the ASN.1
model';
/* CIF NEXTSTATE (670, 416), (100, 50) */
NEXTSTATE Running
/* CIF COMMENT (790, 423), (96, 35) */
COMMENT 'Néxtaytè';
/* CIF ANSWER (94, 236), (100, 35) */
('end'):
/* CIF OUTPUT (88, 286), (112, 50) */
OUTPUT rezult
/* CIF NEXTSTATE (670, 416), (100, 50) */
NEXTSTATE Running
/* CIF COMMENT (790, 423), (96, 35) */
COMMENT 'Néxtaytè';
/* CIF ANSWER (94, 236), (100, 35) */
('end'):
/* CIF OUTPUT (88, 286), (112, 50) */
OUTPUT rezult
('Goodbye!');
/* CIF NEXTSTATE (94, 353), (100, 50) */
NEXTSTATE Wait;
/* CIF ANSWER (258, 236), (100, 35) */
ELSE:
/* CIF TASK (237, 286), (141, 50) */
TASK msg := msg // '!'
/* CIF COMMENT (399, 286), (118, 50) */
COMMENT 'Concatenate
/* CIF NEXTSTATE (94, 353), (100, 50) */
NEXTSTATE Wait;
/* CIF ANSWER (258, 236), (100, 35) */
ELSE:
/* CIF TASK (237, 286), (141, 50) */
TASK msg := msg // '!'
/* CIF COMMENT (399, 286), (118, 50) */
COMMENT 'Concatenate
strings';
/* CIF TASK (210, 351), (195, 50) */
TASK msg := msg(3,4) // msg(1,2)
/* CIF COMMENT (426, 351), (209, 53) */
COMMENT 'Concatenate two substrings
/* CIF TASK (210, 351), (195, 50) */
TASK msg := msg(3,4) // msg(1,2)
/* CIF COMMENT (426, 351), (209, 53) */
COMMENT 'Concatenate two substrings
(can be used to remove an
element from a list)';
/* CIF TASK (226, 416), (163, 50) */
TASK msg := first_msg(1, 2)
/* CIF COMMENT (402, 413), (177, 53) */
COMMENT 'Substring
/* CIF TASK (226, 416), (163, 50) */
TASK msg := first_msg(1, 2)
/* CIF COMMENT (402, 413), (177, 53) */
COMMENT 'Substring
TODO check range
against current Length';
/* CIF OUTPUT (254, 481), (108, 50) */
OUTPUT rezult(msg);
/* CIF NEXTSTATE (258, 546), (100, 50) */
NEXTSTATE Running;
ENDDECISION;
ENDSTATE;
/* CIF STATE (-252, 754), (100, 50) */
STATE Wait;
/* CIF INPUT (-252, 824), (100, 50) */
INPUT go(msg)
/* CIF COMMENT (-132, 831), (120, 35) */
COMMENT 'Ïñpût unicode';
/* CIF DECISION (-259, 889), (114, 70) */
DECISION msg = 'hello'
/* CIF COMMENT (-125, 899), (128, 50) */
COMMENT 'Boolean test
/* CIF OUTPUT (254, 481), (108, 50) */
OUTPUT rezult(msg);
/* CIF NEXTSTATE (258, 546), (100, 50) */
NEXTSTATE Running;
ENDDECISION;
ENDSTATE;
/* CIF STATE (-252, 754), (100, 50) */
STATE Wait;
/* CIF INPUT (-252, 824), (100, 50) */
INPUT go(msg)
/* CIF COMMENT (-132, 831), (120, 35) */
COMMENT 'Ïñpût unicode';
/* CIF DECISION (-259, 889), (114, 70) */
DECISION msg = 'hello'
/* CIF COMMENT (-125, 899), (128, 50) */
COMMENT 'Boolean test
on string value';
/* CIF ANSWER (-41, 979), (100, 35) */
(FALSE):
/* CIF OUTPUT (-60, 1029), (139, 50) */
OUTPUT rezult(first_msg)
/* CIF COMMENT (98, 1036), (85, 35) */
COMMENT 'OûtpUT';
/* CIF NEXTSTATE (-41, 1094), (100, 50) */
NEXTSTATE Wait;
/* CIF ANSWER (-312, 979), (100, 35) */
(TRUE):
/* CIF OUTPUT (-334, 1029), (145, 50) */
OUTPUT rezult('Welcome')
/* CIF COMMENT (-170, 1029), (95, 50) */
COMMENT 'Send raw
/* CIF ANSWER (-41, 979), (100, 35) */
(FALSE):
/* CIF OUTPUT (-60, 1029), (139, 50) */
OUTPUT rezult(first_msg)
/* CIF COMMENT (98, 1036), (85, 35) */
COMMENT 'OûtpUT';
/* CIF NEXTSTATE (-41, 1094), (100, 50) */
NEXTSTATE Wait;
/* CIF ANSWER (-312, 979), (100, 35) */
(TRUE):
/* CIF OUTPUT (-334, 1029), (145, 50) */
OUTPUT rezult('Welcome')
/* CIF COMMENT (-170, 1029), (95, 50) */
COMMENT 'Send raw
string';
/* CIF NEXTSTATE (-312, 1094), (100, 50) */
NEXTSTATE Running;
ENDDECISION;
ENDSTATE;
/* CIF DECISION (-311, 1094), (98, 50) */
DECISION 3 in {1,2,3};
/* CIF ANSWER (-351, 1164), (88, 23) */
(1 in {1,2}):
/* CIF ANSWER (-261, 1164), (88, 23) */
(0 in {1,2}):
ENDDECISION;
/* CIF DECISION (-311, 1222), (98, 50) */
DECISION 4 in {1,2,3};
/* CIF ANSWER (-342, 1292), (70, 23) */
(true):
/* CIF ANSWER (-252, 1292), (70, 23) */
(false):
ENDDECISION;
/* CIF NEXTSTATE (-312, 1345), (100, 50) */
NEXTSTATE Running;
ENDDECISION;
ENDSTATE;
ENDPROCESS og;
\ No newline at end of file
Markdown is supported
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