Commit 418479ad authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Fix operator ranges, and more signed/unsigned

parent 07c5971b
......@@ -1750,7 +1750,8 @@ def _basic_operators(expr):
right_stmts, right_str, right_local = expression(expr.right)
##
#print expr.inputString, " ==> ", left_str, ' and ', right_str,
if isinstance (expr, ogAST.ExprMod):
bt = find_basic_type(expr.exprType)
right_is_numeric, left_is_numeric = True, True
try:
......@@ -1878,7 +1879,16 @@ def _assign_expression(expr):
# Make sure that integers are cast to 64 bits
# No, casting to int64 isn't right if the type is unsigned (asn1scc v4)
# strings.append(u"{} := AsN1Int({});".format(left_str, right_str))
strings.append(u"{} := {};".format(left_str, right_str))
# It is possible that left and right are of different types
# (signed vs unsigned). The parser should have ensured that the
# ranges are compatible. So we can safely cast to the left type
# when right side is of different type.
basic_right = find_basic_type (expr.right.exprType)
if float(basic_right.Min) >= 0 and float (basic_left.Min) < 0:
res = "Asn1Int({})".format(right_str)
else:
res = right_str
strings.append(u"{} := {};".format(left_str, res))
else:
strings.append(u"{} := {};".format(left_str, right_str))
code.extend(left_stmts)
......
......@@ -29,6 +29,7 @@ __author__ = 'Maxime Perrotin'
import sys
import os
import math
import operator
import logging
import traceback
import binascii
......@@ -1318,12 +1319,23 @@ def logic_expression(root, context):
def arithmetic_expression(root, context):
''' Arithmetic expression analysis '''
def find_bounds(operator, minL, maxL, minR, maxR):
candidates = [operator(float(l),float(r))
for l in [minL, maxL]
for r in [minR, maxR]]
return { 'Min': str(min(candidates)),
'Max': str(max(candidates))}
expr, errors, warnings = binary_expression(root, context)
# Expressions returning a numerical type must have their range defined
# accordingly with the kind of opration used between operand:
# accordingly with the kind of operation used between operands:
left = find_basic_type(expr.left.exprType)
right = find_basic_type(expr.right.exprType)
minL = float(left.Min)
maxL = float(left.Max)
minR = float(right.Min)
maxR = float(right.Max)
# Type of the resulting expression depends on whether there are raw numbers
# on one side of the expression (PrInt). By default when they are parsed,
# they are set to 64 bits integers ; but if they are in an expression where
......@@ -1332,23 +1344,22 @@ def arithmetic_expression(root, context):
basic = right if left.__name__ == 'PrInt' else left
try:
if isinstance(expr, ogAST.ExprPlus):
attrs = {'Min': str(float(left.Min) + float(right.Min)),
'Max': str(float(left.Max) + float(right.Max))}
attrs = {'Min': str(minL + minR),
'Max': str(maxL + maxR)}
expr.exprType = type('Plus', (basic,), attrs)
elif isinstance(expr, ogAST.ExprMul):
attrs = {'Min': str(float(left.Min) * float(right.Min)),
'Max': str(float(left.Max) * float(right.Max))}
attrs = find_bounds(operator.mul, minL, maxL, minR, maxR)
expr.exprType = type('Mul', (basic,), attrs)
elif isinstance(expr, ogAST.ExprMinus):
attrs = {'Min': str(float(left.Min) - float(right.Max)),
'Max': str(float(left.Max) - float(right.Min))}
attrs = {'Min': str(minL - maxR),
'Max': str(maxL - minR)}
expr.exprType = type('Minus', (basic,), attrs)
elif isinstance(expr, ogAST.ExprDiv):
attrs = {'Min': str(float(left.Min) / (float(right.Max) or 1)),
'Max': str(float(left.Max) / (float(right.Min) or 1))}
attrs = find_bounds(operator.truediv, minL, maxL, minR or 1,
maxR or 1)
expr.exprType = type('Div', (basic,), attrs)
elif isinstance(expr, (ogAST.ExprMod, ogAST.ExprRem)):
attrs = {'Min': right.Min, 'Max': right.Max}
attrs = {'Min': '0', 'Max': right.Max}
expr.exprType = type('Mod', (basic,), attrs)
except (ValueError, AttributeError):
msg = 'Check that all your numerical data types '\
......@@ -4150,6 +4161,7 @@ def assign(root, context):
if not errors:
if expr.right.exprType == UNKNOWN_TYPE or not \
isinstance(expr.right, (ogAST.ExprAppend,
ogAST.ExprMod,
ogAST.PrimSequenceOf,
ogAST.PrimStringLiteral)):
expr.right.exprType = expr.left.exprType
......@@ -4164,7 +4176,6 @@ def assign(root, context):
# Set the expected type on the right, this is needed to know
# if the expected size is variable or fixed in backends
expr.right.expected_type = expr.left.exprType
return expr, errors, warnings
......
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