Commit 0ebeef6e authored by dbarbera's avatar dbarbera
Browse files

Added unary expressions nodes

parent 0d5c683e
......@@ -723,8 +723,7 @@ def _primary_variable(prim):
''' Single variable reference '''
sep = u'l_' if find_var(prim.value[0]) else u''
string = u'{sep}{name}'.format(sep=sep, name=prim.value[0])
ada_string = unary(prim, string)
ada_string = u'{sep}{name}'.format(sep=sep, name=prim.value[0])
if prim.exprType.__name__ == 'for_range':
# Ada iterator in FOR loops is an Integer - we must cast to 64 bits
......@@ -896,7 +895,6 @@ def _prim_path(primary_id):
ada_string += ', '.join(list_of_params)
ada_string += ')'
sep = '.'
ada_string = unary(primary_id, ada_string)
return stmts, ada_string, local_decl
......@@ -924,7 +922,6 @@ def _basic_operators(expr):
code.extend(right_stmts)
local_decl.extend(left_local)
local_decl.extend(right_local)
ada_string = unary(expr, ada_string)
return code, ada_string, local_decl
......@@ -964,7 +961,18 @@ def _bitwise_operators(expr):
code.extend(right_stmts)
local_decl.extend(left_local)
local_decl.extend(right_local)
ada_string = unary(expr, ada_string)
return code, ada_string, local_decl
@expression.register(ogAST.ExprNot)
@expression.register(ogAST.ExprNeg)
def _unary_operator(expr):
''' Generate the code for an unary expression '''
code, local_decl = [], []
expr_stmts, expr_str, expr_local = expression(expr.expr)
ada_string = u'({op} {expr})'.format(op=expr.operand, expr=expr_str)
code.extend(expr_stmts)
local_decl.extend(expr_local)
return code, ada_string, local_decl
......@@ -1090,8 +1098,11 @@ def _choice_determinant(primary):
@expression.register(ogAST.PrimReal)
def _integer(primary):
''' Generate code for a raw numerical value '''
if float(primary.value[0]) < 0:
# Parentesize negative integers for maintaining the precedence in the generated code
ada_string = '({})'.format(primary.value[0])
else:
ada_string = primary.value[0]
ada_string = unary(primary, ada_string)
return [], ada_string, []
......@@ -1099,7 +1110,6 @@ def _integer(primary):
def _integer(primary):
''' Generate code for a raw boolean value '''
ada_string = primary.value[0]
ada_string = unary(primary, ada_string)
return [], ada_string, []
......@@ -1514,25 +1524,6 @@ def _inner_procedure(proc):
return code, local_decl
# A few helper functions needed by the Ada backend
def unary(expr, string):
''' Check for NOT or MINUS unary operators and add them to the string '''
op_minus = getattr(expr, 'op_minus', False)
op_not = getattr(expr, 'op_not', False)
try:
float_val = float(string)
except ValueError:
float_val = 1
if op_minus and float_val > 0:
string = u'(-{})'.format(string)
elif float_val <= 0:
string = u'({})'.format(string)
if op_not:
string = u'not {}'.format(string)
return string
def find_basic_type(a_type):
''' Return the ASN.1 basic type of a_type '''
basic_type = a_type
......
......@@ -127,6 +127,14 @@ class ExprRem(Expression):
operand = 'rem'
class ExprNot(Expression):
operand = 'not'
class ExprNeg(Expression):
operand = '-'
class ExprAssign(Expression):
operand = ':='
......@@ -157,16 +165,12 @@ class Primary(Expression):
self.inputString = primary.inputString
self.line = primary.line
self.charPositionInLine = primary.charPositionInLine
self.op_not = primary.op_not
self.op_minus = primary.op_minus
self.value = primary.value
self.exprType = primary.exprType
else:
self.inputString = inputString
self.line = line
self.charPositionInLine = charPositionInLine
self.op_not = False
self.op_minus = False
self.value = None
self.exprType = None
......
......@@ -61,6 +61,8 @@ OPKIND = {lexer.PLUS: ogAST.ExprPlus,
lexer.APPEND: ogAST.ExprAppend,
lexer.IN: ogAST.ExprIn,
lexer.REM: ogAST.ExprRem,
lexer.NOT: ogAST.ExprNot,
lexer.NEG: ogAST.ExprNeg,
lexer.PRIMARY: ogAST.Primary}
# Insert current path in the search list for importing modules
......@@ -861,8 +863,28 @@ def find_type(path, context):
return result
def fix_expression_type(expr, context):
''' Check/ensure type consistency in unary expressions '''
if expr.expr.exprType == UNKNOWN_TYPE \
and isinstance(expr.expr, ogAST.PrimPath) \
and len(expr.expr.value) == 1:
try:
exprType = find_variable(expr.expr.value[0], context)
# Differentiate DCL and FPAR variables
use_type = ogAST.PrimVariable
if isinstance(context, ogAST.Procedure):
for each in context.fpar:
if each['name'].lower() == expr.expr.value[0].lower():
use_type = ogAST.PrimFPAR
break
expr.expr = use_type(primary=expr.expr)
expr.expr.exprType = exprType
except AttributeError:
pass
def fix_expression_types(expr, context):
''' Check/ensure type consistency in expressions having two sides '''
''' Check/ensure type consistency in binary expressions '''
if isinstance(expr, ogAST.Primary):
return
......@@ -1249,14 +1271,9 @@ def primary(root, context):
''' Process a primary (-/NOT value) '''
warnings = []
errors = []
op_not, op_minus = False, False
prim = None
for child in root.getChildren():
if child.type == lexer.NOT:
op_not = True
elif child.type == lexer.MINUS:
op_minus = True
elif child.type == lexer.PRIMARY_ID:
if child.type == lexer.PRIMARY_ID:
# Variable reference, indexed values, or ASN.1 value notation
prim, err, warn = primary_value(child, context=context)
errors.extend(err)
......@@ -1292,10 +1309,6 @@ def primary(root, context):
prim.inputString = get_input_string(root)
prim.line = root.getLine()
prim.charPositionInLine = root.getCharPositionInLine()
if op_not:
prim.op_not = True
if op_minus:
prim.op_minus = True
return prim, errors, warnings
......@@ -1325,7 +1338,7 @@ def expression(root, context):
root.children.pop(idx)
break
# Binary expressions
if root.type in (lexer.PLUS,
lexer.ASTERISK,
lexer.DASH,
......@@ -1374,6 +1387,15 @@ def expression(root, context):
format(expr.inputString, str(report)))
expr = new_expr
# Unary expressions
elif root.type in (lexer.NOT, lexer.NEG):
child = root.getChildren()[0]
expr.expr, err_expr, warn_expr = expression(child, context)
errors.extend(err_expr)
warnings.extend(warn_expr)
fix_expression_type(expr, context)
if root.type in (lexer.EQ,
lexer.NEQ,
lexer.GT,
......@@ -1414,7 +1436,6 @@ def expression(root, context):
errors.append('Check that all your numerical data types have '
'a range constraint')
elif root.type in (lexer.OR, lexer.AND, lexer.XOR):
# in the case of bitwise operators, if both sides are arrays,
# then the result is an array too
......@@ -1425,15 +1446,22 @@ def expression(root, context):
else:
expr.exprType = expr.left.exprType
elif root.type in (lexer.PLUS,
lexer.ASTERISK,
lexer.DASH,
lexer.DIV,
lexer.APPEND,
lexer.REM,
lexer.MOD):
elif root.type == lexer.NOT:
basic = find_basic_type(expr.expr.exprType)
if basic.kind == 'BooleanType':
expr.exprType = BOOLEAN
else:
expr.exprType = expr.expr.exprType
elif root.type == lexer.APPEND:
expr.exprType = expr.left.exprType
elif root.type == lexer.NEG:
basic = find_basic_type(expr.expr.exprType)
attrs = {'Min': str(-float(basic.Max)),
'Max': str(-float(basic.Min))}
expr.exprType = type('Neg', (basic,), attrs)
if root.type == lexer.PRIMARY:
expr, err, warn = primary(root, context)
if not expr:
......
......@@ -89,7 +89,7 @@ tokens {
VARIABLES;
SORT;
DCL;
MINUS;
NEG;
GROUND;
TEXTAREA;
TEXTAREA_CONTENT;
......@@ -795,18 +795,28 @@ variable
field_selection
: (('!'|'.') field_name);
expression : operand0 ( IMPLIES^ operand0)* ;
operand0 : operand1 (( (OR^ ELSE?) | XOR^ ) operand1)*;
operand1 : operand2 ( AND^ THEN? operand2)*;
operand2 : operand3
(( EQ^ | NEQ^ | GT^ | GE^ | LT^ | LE^ | IN^ )
operand3)*;
operand3 : operand4 (( PLUS^ | DASH^ | APPEND^ ) operand4)*;
operand4 : operand5
(( ASTERISK^ | DIV^ | MOD^ | REM^ ) operand5)*;
operand5 : primary_qualifier? primary
-> ^(PRIMARY primary_qualifier? primary);
expression
: operand0 ( IMPLIES^ operand0)* ;
operand0
: operand1 (( (OR^ ELSE?) | XOR^ ) operand1)*;
operand1
: operand2 ( AND^ THEN? operand2)*;
operand2
: operand3 (( EQ^ | NEQ^ | GT^ | GE^ | LT^ | LE^ | IN^ ) operand3)*;
operand3
: operand4 (( PLUS^ | DASH^ | APPEND^ ) operand4)*;
operand4
: operand5 (( ASTERISK^ | DIV^ | MOD^ | REM^ ) operand5)*;
operand5
: primary -> ^(PRIMARY primary)
| NOT^ operand5
| DASH operand5 -> ^(NEG operand5);
// primary below covers all cases including ASN.1 Value Notation
primary
......@@ -869,12 +879,6 @@ namedValue
: ID expression;
primary_qualifier
: DASH
-> ^(MINUS)
| NOT;
primary_params
: '(' expression_list ')'
-> ^(PARAMS expression_list)
......
This diff is collapsed.
This diff is collapsed.
/* CIF PROCESS (148, 150), (150, 75) */
PROCESS myfunction;
/* CIF TEXT (0, 17), (296, 428) */
/* CIF TEXT (0, 17), (296, 456) */
-- Timers defined in the interface view
-- Use SET_TIMER (value, timer name)
-- and RESET_TIMER (timer name) in a
......@@ -22,7 +22,7 @@ dcl someInt t_uInt8 := 2;
dcl otherint T_uint8 := 1;
-- To test 'op_not'
dcl opnot T_boolean := not true;
dcl opnot T_boolean := false;
-- To test writeln with octet strings
dcl str MyOctStr := 'abc';
dcl variable_str String := 'Hello!';
......@@ -49,14 +49,14 @@ endfor;
ENDPROCEDURE;
/* CIF START (591, 0), (100, 50) */
START;
/* CIF PROCEDURECALL (553, 65), (175, 35) */
/* CIF PROCEDURECALL (552, 65), (176, 35) */
CALL writeln(-(someint + 1))
/* CIF COMMENT (748, 65), (226, 38) */
/* CIF COMMENT (748, 65), (227, 40) */
COMMENT 'Test unary on expression result
should display -3';
/* CIF PROCEDURECALL (542, 115), (197, 35) */
CALL writeln(not(true or false))
/* CIF COMMENT (759, 115), (187, 38) */
/* CIF COMMENT (759, 115), (187, 40) */
COMMENT 'test unary on expression
should display FALSE';
/* CIF PROCEDURECALL (586, 165), (110, 35) */
......@@ -69,15 +69,15 @@ should display FALSE';
COMMENT 'Write again to check local variables';
/* CIF PROCEDURECALL (558, 265), (165, 35) */
CALL writeln(variable_str)
/* CIF COMMENT (743, 265), (275, 35) */
/* CIF COMMENT (743, 265), (278, 35) */
COMMENT 'Write a non-fixed length OCTET STRING';
/* CIF PROCEDURECALL (541, 315), (199, 38) */
CALL writeln(variable_str // '!!!')
/* CIF COMMENT (760, 316), (117, 35) */
/* CIF COMMENT (760, 316), (119, 35) */
COMMENT 'with APPEND';
/* CIF PROCEDURECALL (465, 368), (352, 35) */
CALL writeln(if someint>0 then variable_str else other fi)
/* CIF COMMENT (837, 368), (275, 35) */
/* CIF COMMENT (837, 368), (278, 35) */
COMMENT 'Write a non-fixed lenght OCTET STRING';
/* CIF PROCEDURECALL (552, 418), (177, 35) */
CALL writeln(1 + (-otherint))
......@@ -85,17 +85,17 @@ should display FALSE';
COMMENT 'Test the op_minus in a sub-expression';
/* CIF PROCEDURECALL (430, 468), (421, 35) */
CALL writeln(-someint, if someint>0 then ' is ' else 'Foo' fi, not true)
/* CIF COMMENT (871, 468), (291, 35) */
/* CIF COMMENT (871, 468), (292, 35) */
COMMENT 'Various tests with strings, ternary, op_not';
/* CIF PROCEDURECALL (514, 518), (254, 35) */
CALL write(if someint>0 then 2 else 1 fi)
/* CIF COMMENT (788, 518), (220, 35) */
/* CIF COMMENT (788, 518), (221, 35) */
COMMENT 'test ternary with raw numbers';
/* CIF PROCEDURECALL (496, 568), (289, 35) */
CALL write(if someint>0 then someint else 1 fi)
/* CIF COMMENT (805, 568), (308, 35) */
/* CIF COMMENT (805, 568), (310, 35) */
COMMENT 'test ternary with mixed variable/raw number';
/* CIF PROCEDURECALL (577, 618), (128, 35) */
/* CIF PROCEDURECALL (576, 618), (129, 35) */
CALL writeln(bar(1))
/* CIF COMMENT (725, 618), (100, 35) */
COMMENT 'test index';
......@@ -103,63 +103,63 @@ should display FALSE';
CALL writeln(opnot, ' ', not opnot)
/* CIF COMMENT (769, 668), (191, 35) */
COMMENT 'test op_not with variable';
/* CIF TASK (480, 718), (321, 35) */
/* CIF TASK (478, 718), (324, 35) */
TASK someInt := if someint = 0 then someint else 0 fi;
/* CIF DECISION (504, 768), (273, 87) */
/* CIF DECISION (501, 768), (278, 87) */
DECISION someint /=0 and then (10 / someInt > 0)
or else someint = 0
/* CIF COMMENT (793, 777), (179, 68) */
/* CIF COMMENT (795, 777), (179, 72) */
COMMENT 'Using "and else" is the
short-circuit form. The
second part should not
be evaluated.';
/* CIF ANSWER (561, 875), (70, 23) */
/* CIF ANSWER (561, 875), (70, 24) */
(true):
/* CIF TASK (541, 913), (110, 35) */
/* CIF TASK (540, 914), (111, 35) */
TASK someInt := 2;
/* CIF PROCEDURECALL (537, 963), (117, 38) */
/* CIF PROCEDURECALL (536, 964), (118, 38) */
CALL writeln('OK');
/* CIF ANSWER (664, 875), (70, 23) */
/* CIF ANSWER (662, 875), (70, 24) */
(false):
ENDDECISION;
/* CIF NEXTSTATE (608, 1016), (65, 33) */
/* CIF NEXTSTATE (605, 1017), (68, 33) */
NEXTSTATE Wait;
/* CIF STATE (608, 1016), (65, 33) */
/* CIF STATE (605, 1017), (68, 33) */
STATE Wait;
/* CIF INPUT (865, 1069), (89, 33) */
/* CIF INPUT (863, 1070), (90, 33) */
INPUT mytimer;
/* CIF PROCEDURECALL (818, 1117), (182, 33) */
/* CIF PROCEDURECALL (818, 1118), (182, 33) */
CALL writeln('timer expired');
/* CIF PROCEDURECALL (829, 1165), (160, 33) */
/* CIF PROCEDURECALL (828, 1166), (161, 33) */
CALL factorial(3, someint);
/* CIF NEXTSTATE (877, 1213), (65, 33) */
/* CIF NEXTSTATE (874, 1214), (68, 33) */
NEXTSTATE Wait;
/* CIF INPUT (421, 1069), (181, 33) */
/* CIF INPUT (421, 1070), (181, 33) */
INPUT start_something (toto);
/* CIF OUTPUT (376, 1117), (270, 33) */
/* CIF OUTPUT (373, 1118), (275, 33) */
OUTPUT result_data((toto+1) mod 2147483647);
/* CIF PROCEDURECALL (436, 1165), (150, 48) */
/* CIF PROCEDURECALL (436, 1166), (150, 48) */
CALL writeln
('Hello Toto', toto);
/* CIF PROCEDURECALL (413, 1228), (196, 33) */
/* CIF PROCEDURECALL (412, 1229), (198, 33) */
CALL set_timer(1000, myTimer);
/* CIF TASK (346, 1276), (330, 35) */
/* CIF TASK (346, 1277), (330, 35) */
TASK largeReal := power(someReal, 2);
/* CIF PROCEDURECALL (282, 1326), (458, 35) */
/* CIF PROCEDURECALL (282, 1327), (458, 35) */
CALL writeln(someReal, ' ** 2' , ' == ', largeReal, ' (should be 2.25 )');
/* CIF TASK (411, 1376), (201, 35) */
/* CIF TASK (410, 1377), (201, 35) */
TASK someReal := float(someInt);
/* CIF TASK (391, 1426), (241, 35) */
/* CIF TASK (389, 1427), (243, 35) */
TASK someInt := fix(someReal) mod 255;
/* CIF TASK (435, 1476), (152, 35) */
/* CIF TASK (434, 1477), (153, 35) */
TASK opnot := not opnot;
/* CIF TASK (430, 1526), (163, 35) */
/* CIF TASK (429, 1527), (164, 35) */
TASK 'someint := -someint'
/* CIF COMMENT (613, 1526), (196, 35) */
/* CIF COMMENT (613, 1527), (196, 35) */
COMMENT 'XXX should raise an error!';
/* CIF TASK (429, 1576), (164, 35) */
/* CIF TASK (428, 1577), (165, 35) */
TASK someint := (-8) mod 5;
/* CIF NEXTSTATE (480, 1626), (63, 33) */
/* CIF NEXTSTATE (478, 1627), (66, 33) */
NEXTSTATE wait;
ENDSTATE;
ENDPROCESS myfunction;
\ 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