Commit 5bb148ab authored by dbarbera's avatar dbarbera
Browse files

Add support for ASN.1 constants

parent b0421901
...@@ -39,6 +39,7 @@ class Context(): ...@@ -39,6 +39,7 @@ class Context():
self.module = lc.Module.new(self.name) self.module = lc.Module.new(self.name)
self.target_data = le.TargetData.new(self.module.data_layout) self.target_data = le.TargetData.new(self.module.data_layout)
self.dataview = process.dataview self.dataview = process.dataview
self.procedures = process.procedures self.procedures = process.procedures
self.scope = Scope(self) self.scope = Scope(self)
...@@ -350,10 +351,10 @@ class Scope: ...@@ -350,10 +351,10 @@ class Scope:
self.parent = parent self.parent = parent
def define(self, name, var): def define(self, name, var):
self.vars[name.lower()] = var self.vars[name.lower().replace('-', '_')] = var
def resolve(self, name): def resolve(self, name):
var = self.vars.get(name.lower()) var = self.vars.get(name.lower().replace('-', '_'))
if var: if var:
return var return var
if self.parent: if self.parent:
...@@ -411,6 +412,12 @@ def _process(process, ctx=None): ...@@ -411,6 +412,12 @@ def _process(process, ctx=None):
state_cons.initializer = lc.Constant.int(ctx.i32, -1) state_cons.initializer = lc.Constant.int(ctx.i32, -1)
ctx.scope.define('.state', state_cons) ctx.scope.define('.state', state_cons)
# Generate ASN.1 constants
for name, t in process.dv.variables.viewitems():
var_llty = ctx.lltype_of(t.type)
global_var = ctx.module.add_global_variable(var_llty, str(name))
ctx.scope.define(str(name).lower(), global_var)
# Generare process-level vars # Generare process-level vars
for name, (asn1ty, expr) in process.variables.viewitems(): for name, (asn1ty, expr) in process.variables.viewitems():
var_llty = ctx.lltype_of(asn1ty) var_llty = ctx.lltype_of(asn1ty)
...@@ -1460,7 +1467,8 @@ def _prim_string_literal(prim, ctx): ...@@ -1460,7 +1467,8 @@ def _prim_string_literal(prim, ctx):
@expression.register(ogAST.PrimConstant) @expression.register(ogAST.PrimConstant)
def _prim_constant(prim, ctx): def _prim_constant(prim, ctx):
''' Generate the IR for a reference to an ASN.1 constant ''' ''' Generate the IR for a reference to an ASN.1 constant '''
raise NotImplementedError var_ptr = ctx.global_scope.resolve(prim.value[0])
return var_ptr if is_struct_ptr(var_ptr) else ctx.builder.load(var_ptr)
@expression.register(ogAST.PrimMantissaBaseExp) @expression.register(ogAST.PrimMantissaBaseExp)
......
...@@ -400,21 +400,6 @@ def find_basic_type(a_type): ...@@ -400,21 +400,6 @@ def find_basic_type(a_type):
return basic_type return basic_type
def is_constant(var):
''' Check in ASN.1 modules if var (Primary) is declared as a constant '''
if var is None:
return False
if isinstance(var, ogAST.PrimConstant):
return True
if DV and isinstance(var, ogAST.PrimVariable):
for mod in DV.asn1Modules:
for constant in DV.exportedVariables[mod]:
if(constant.lower() == var.value[0].lower().replace('_', '-')):
LOG.debug('Constant ' + var.inputString + ' found')
return True
return False
def signature(name, context): def signature(name, context):
''' Return the signature of a procecure/output/operator ''' ''' Return the signature of a procecure/output/operator '''
name = name.lower() name = name.lower()
...@@ -605,9 +590,7 @@ def check_type_compatibility(primary, type_ref, context): ...@@ -605,9 +590,7 @@ def check_type_compatibility(primary, type_ref, context):
assert type_ref is not None assert type_ref is not None
if type_ref is UNKNOWN_TYPE: if type_ref is UNKNOWN_TYPE:
raise TypeError('Type reference is unknown') raise TypeError('Type reference is unknown')
if isinstance(primary, ogAST.PrimConstant):
# ASN.1 constants type is unknown (Asn1 backend to be completed)
return
basic_type = find_basic_type(type_ref) basic_type = find_basic_type(type_ref)
LOG.debug("[check_type_compatibility] " LOG.debug("[check_type_compatibility] "
"checking if {value} is of type {typeref}" "checking if {value} is of type {typeref}"
...@@ -817,12 +800,14 @@ def compare_types(type_a, type_b): ...@@ -817,12 +800,14 @@ def compare_types(type_a, type_b):
)) ))
def find_variable(var, context): def find_variable_type(var, context):
''' Look for a variable name in the context and return its type ''' ''' Look for a variable name in the context and return its type '''
LOG.debug('[find_variable] checking if ' + str(var) + ' is defined') LOG.debug('[find_variable] checking if ' + str(var) + ' is defined')
# all DCL-variables # all DCL-variables
all_visible_variables = dict(context.global_variables) all_visible_variables = dict(context.global_variables)
all_visible_variables.update(context.variables) all_visible_variables.update(context.variables)
# First check locally, i.e. in FPAR # First check locally, i.e. in FPAR
try: try:
for variable in context.fpar: for variable in context.fpar:
...@@ -844,6 +829,12 @@ def find_variable(var, context): ...@@ -844,6 +829,12 @@ def find_variable(var, context):
LOG.debug(str(var) + ' is defined') LOG.debug(str(var) + ' is defined')
return TIMER return TIMER
# check if is a ASN.1 constant
for varname, vartype in DV.variables.viewitems():
if var.lower() == varname.lower().replace('-', '_'):
LOG.debug(str(var) + ' is defined')
return vartype.type
LOG.debug('[find_variable] result: not found, raising exception') LOG.debug('[find_variable] result: not found, raising exception')
raise AttributeError('Variable {var} not defined'.format(var=var)) raise AttributeError('Variable {var} not defined'.format(var=var))
...@@ -887,13 +878,6 @@ def fix_expression_types(expr, context): ...@@ -887,13 +878,6 @@ def fix_expression_types(expr, context):
# except (UnboundLocalError, AttributeError, TypeError): # except (UnboundLocalError, AttributeError, TypeError):
# pass # pass
# If a side type remains unknown, check if it is an ASN.1 constant
for side in permutations(('left', 'right')):
value = getattr(expr, side[0])
if value.exprType == UNKNOWN_TYPE and is_constant(value):
setattr(expr, side[0], ogAST.PrimConstant(primary=value))
getattr(expr, side[0]).exprType = getattr(expr, side[1]).exprType
for side in (expr.right, expr.left): for side in (expr.right, expr.left):
if side.is_raw: if side.is_raw:
raw_expr = side raw_expr = side
...@@ -1010,30 +994,46 @@ def expression_list(root, context): ...@@ -1010,30 +994,46 @@ def expression_list(root, context):
def primary_variable(root, context): def primary_variable(root, context):
''' Primary Variable analysis ''' ''' Primary Variable analysis '''
lexeme = root.children[0].text name = root.children[0].text
errors, warnings = [], []
# Differentiate DCL and FPAR variables if is_asn1constant(name):
Prim = ogAST.PrimVariable prim = ogAST.PrimConstant()
if isinstance(context, ogAST.Procedure): elif is_fpar(name, context):
for each in context.fpar: prim = ogAST.PrimFPAR()
if each['name'].lower() == lexeme.lower(): else:
Prim = ogAST.PrimFPAR prim = ogAST.PrimVariable()
break
prim, errors, warnings = Prim(), [], [] prim.value = [name]
prim.value = [root.children[0].text]
prim.exprType = UNKNOWN_TYPE prim.exprType = UNKNOWN_TYPE
prim.inputString = get_input_string(root) prim.inputString = get_input_string(root)
prim.tmpVar = tmp() prim.tmpVar = tmp()
try: try:
prim.exprType = find_variable(lexeme, context) prim.exprType = find_variable_type(name, context)
except AttributeError: except AttributeError:
pass pass
return prim, errors, warnings return prim, errors, warnings
def is_fpar(name, context):
name = name.lower()
if isinstance(context, ogAST.Procedure):
for each in context.fpar:
if each['name'].lower() == name:
return True
return False
def is_asn1constant(name):
name = name.lower().replace('-', '_')
for varname, vartype in DV.variables.viewitems():
if varname.lower().replace('-', '_') == name:
return True
return False
def binary_expression(root, context): def binary_expression(root, context):
''' Binary expression analysis ''' ''' Binary expression analysis '''
errors, warnings = [], [] errors, warnings = [], []
...@@ -1716,7 +1716,8 @@ def variables(root, ta_ast, context): ...@@ -1716,7 +1716,8 @@ def variables(root, ta_ast, context):
else: else:
def_value.exprType = asn1_sort def_value.exprType = asn1_sort
if not def_value.is_raw and not is_constant(def_value): if not def_value.is_raw and \
not isinstance(def_value, ogAST.PrimConstant):
errors.append('In variable declaration {}: default' errors.append('In variable declaration {}: default'
' value is not a valid ground expression'. ' value is not a valid ground expression'.
format(var[-1])) format(var[-1]))
...@@ -2562,7 +2563,7 @@ def input_part(root, parent, context): ...@@ -2562,7 +2563,7 @@ def input_part(root, parent, context):
len(inputparams[0]) == 1: len(inputparams[0]) == 1:
user_param, = inputparams[0] user_param, = inputparams[0]
try: try:
user_param_type = find_variable(user_param.text, context) user_param_type = find_variable_type(user_param.text, context)
try: try:
compare_types(sig_param_type, user_param_type) compare_types(sig_param_type, user_param_type)
except TypeError as err: except TypeError as err:
...@@ -3817,6 +3818,7 @@ def pr_file(root): ...@@ -3817,6 +3818,7 @@ def pr_file(root):
ast.processes.append(process) ast.processes.append(process)
process.dataview = types() process.dataview = types()
process.asn1Modules = ast.asn1Modules process.asn1Modules = ast.asn1Modules
process.dv = DV
errors.extend(err) errors.extend(err)
warnings.extend(warn) warnings.extend(warn)
LOG.debug('all files: ' + str(ast.pr_files)) LOG.debug('all files: ' + str(ast.pr_files))
......
...@@ -17,4 +17,6 @@ Choice ::= CHOICE { ...@@ -17,4 +17,6 @@ Choice ::= CHOICE {
f Real f Real
} }
pi Real ::= 3.14159265359
END END
...@@ -25,7 +25,7 @@ DCL c Choice := i:2; ...@@ -25,7 +25,7 @@ DCL c Choice := i:2;
/* CIF PROCEDURECALL (-22, 324), (293, 35) */ /* CIF PROCEDURECALL (-22, 324), (293, 35) */
CALL assert(ceil(f + 0.5) = 3.0, 'ceil(f + 0.5) = 3.0'); CALL assert(ceil(f + 0.5) = 3.0, 'ceil(f + 0.5) = 3.0');
/* CIF PROCEDURECALL (-90, 374), (429, 35) */ /* CIF PROCEDURECALL (-90, 374), (429, 35) */
CALL assert(round(cos(3.141632)) = -1.0, 'round(cos(3.141632)) = -1.0'); CALL assert(round(cos(pi)) = -1.0, 'round(cos(pi)) = -1.0');
/* CIF PROCEDURECALL (12, 424), (224, 35) */ /* CIF PROCEDURECALL (12, 424), (224, 35) */
CALL assert(fix(f) = i, 'fix(f) = i'); CALL assert(fix(f) = i, 'fix(f) = i');
/* CIF PROCEDURECALL (-1, 474), (251, 35) */ /* CIF PROCEDURECALL (-1, 474), (251, 35) */
...@@ -41,7 +41,7 @@ DCL c Choice := i:2; ...@@ -41,7 +41,7 @@ DCL c Choice := i:2;
/* CIF PROCEDURECALL (-14, 724), (276, 35) */ /* CIF PROCEDURECALL (-14, 724), (276, 35) */
CALL assert(power(i, 3) = 8, 'power(i, 3) = 8'); CALL assert(power(i, 3) = 8, 'power(i, 3) = 8');
/* CIF PROCEDURECALL (-90, 774), (429, 35) */ /* CIF PROCEDURECALL (-90, 774), (429, 35) */
CALL assert(round(sin(3.141632)) = 0.0, 'round(sin(3.141632)) = 0.0'); CALL assert(round(sin(pi)) = 0.0, 'round(sin(pi)) = 0.0');
/* CIF PROCEDURECALL (-15, 824), (278, 35) */ /* CIF PROCEDURECALL (-15, 824), (278, 35) */
CALL assert(sqrt(16.0) = 4.0, 'sqrt(16.0) = 4.0'); CALL assert(sqrt(16.0) = 4.0, 'sqrt(16.0) = 4.0');
/* CIF PROCEDURECALL (-26, 874), (301, 35) */ /* CIF PROCEDURECALL (-26, 874), (301, 35) */
......
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