Commit 892e0f98 authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Minor code refactoring

parent 7abbb982
This diff is collapsed.
...@@ -12,9 +12,14 @@ ...@@ -12,9 +12,14 @@
A Visitor Pattern using Python's "singledispatch" mechanism is used A Visitor Pattern using Python's "singledispatch" mechanism is used
to go through the AST and generate code for each SDL construct. to go through the AST and generate code for each SDL construct.
There is a single function called "generate", decorated with the At top-level there is a function called "generate", decorated with the
singledispatch mechanism, that needs to be called to generate the code singledispatch mechanism, that needs to be called to generate the code
of any AST element. of an AST construct.
Expressions have to be generated from the "expression" function.
Optionnaly use the Helper module functions to flatten the model,
rename symbols, etc. (see AdaGenerator.py).
Copyright (c) 2012-2014 European Space Agency Copyright (c) 2012-2014 European Space Agency
...@@ -36,8 +41,25 @@ __all__ = ['generate'] ...@@ -36,8 +41,25 @@ __all__ = ['generate']
@singledispatch @singledispatch
def generate(ast): def generate(ast):
''' Generate the code for an item of the AST ''' ''' Generate the code for an item of the AST
Should typically return:
- a list of statements
- a list of needed local variables
'''
raise TypeError('[Backend] Unsupported AST construct') raise TypeError('[Backend] Unsupported AST construct')
# return [], []
@singledispatch
def expression(expr):
''' Generate the code for Expression-classes, returning 3 things:
- list of statements
- useable string corresponding to the evaluation of the expression,
- list of local declarations
'''
_ = expr
raise TypeError('Unsupported expression: ' + str(expr))
# return [], '', []
# Processing of the AST # Processing of the AST
...@@ -78,14 +100,45 @@ def _task_forloop(task): ...@@ -78,14 +100,45 @@ def _task_forloop(task):
''' '''
pass pass
@generate.register(ogAST.Decision)
def _decision(dec):
''' generate the code for a decision '''
pass
@generate.register(ogAST.PrimVariable) @generate.register(ogAST.Label)
def _label(tr):
''' Transition following labels should be generated in a separate section
for visibility reasons
'''
pass
@generate.register(ogAST.Transition)
def _transition(tr):
''' generate the code for a transition '''
pass
@generate.register(ogAST.Floating_label)
def _floating_label(label):
''' Generate the code for a floating label (label + transition) '''
pass
@generate.register(ogAST.Procedure)
def _inner_procedure(proc):
''' Generate the code for a procedure '''
pass
@expression.register(ogAST.PrimVariable)
def _primary_variable(prim): def _primary_variable(prim):
''' Single variable reference ''' ''' Single variable reference '''
pass pass
@generate.register(ogAST.PrimPath) # Expressions
@expression.register(ogAST.PrimPath)
def _prim_path(primaryId): def _prim_path(primaryId):
''' '''
Return the string of an element list (path) Return the string of an element list (path)
...@@ -99,139 +152,109 @@ def _prim_path(primaryId): ...@@ -99,139 +152,109 @@ def _prim_path(primaryId):
pass pass
@generate.register(ogAST.ExprPlus) @expression.register(ogAST.ExprPlus)
@generate.register(ogAST.ExprMul) @expression.register(ogAST.ExprMul)
@generate.register(ogAST.ExprMinus) @expression.register(ogAST.ExprMinus)
@generate.register(ogAST.ExprEq) @expression.register(ogAST.ExprEq)
@generate.register(ogAST.ExprNeq) @expression.register(ogAST.ExprNeq)
@generate.register(ogAST.ExprGt) @expression.register(ogAST.ExprGt)
@generate.register(ogAST.ExprGe) @expression.register(ogAST.ExprGe)
@generate.register(ogAST.ExprLt) @expression.register(ogAST.ExprLt)
@generate.register(ogAST.ExprLe) @expression.register(ogAST.ExprLe)
@generate.register(ogAST.ExprDiv) @expression.register(ogAST.ExprDiv)
@generate.register(ogAST.ExprMod) @expression.register(ogAST.ExprMod)
@generate.register(ogAST.ExprRem) @expression.register(ogAST.ExprRem)
@generate.register(ogAST.ExprAssign) @expression.register(ogAST.ExprAssign)
def _basic_operators(expr): def _basic_operators(expr):
''' Expressions with two sides ''' ''' Expressions with two sides '''
pass pass
@generate.register(ogAST.ExprOr) @expression.register(ogAST.ExprOr)
@generate.register(ogAST.ExprAnd) @expression.register(ogAST.ExprAnd)
@generate.register(ogAST.ExprXor) @expression.register(ogAST.ExprXor)
def _bitwise_operators(expr): def _bitwise_operators(expr):
''' Logical operators ''' ''' Logical operators '''
pass pass
@generate.register(ogAST.ExprAppend) @expression.register(ogAST.ExprAppend)
def _append(expr): def _append(expr):
''' Generate code for the APPEND construct: a // b ''' ''' Generate code for the APPEND construct: a // b '''
pass pass
@generate.register(ogAST.ExprIn) @expression.register(ogAST.ExprIn)
def _expr_in(expr): def _expr_in(expr):
''' IN expressions: check if item is in a SEQUENCE OF ''' ''' IN expressions: check if item is in a SEQUENCE OF '''
pass pass
@generate.register(ogAST.PrimEnumeratedValue) @expression.register(ogAST.PrimEnumeratedValue)
def _enumerated_value(primary): def _enumerated_value(primary):
''' Generate code for an enumerated value ''' ''' Generate code for an enumerated value '''
pass pass
@generate.register(ogAST.PrimChoiceDeterminant) @expression.register(ogAST.PrimChoiceDeterminant)
def _choice_determinant(primary): def _choice_determinant(primary):
''' Generate code for a choice determinant (enumerated) ''' ''' Generate code for a choice determinant (enumerated) '''
pass pass
@generate.register(ogAST.PrimInteger) @expression.register(ogAST.PrimInteger)
@generate.register(ogAST.PrimReal) @expression.register(ogAST.PrimReal)
@generate.register(ogAST.PrimBoolean) @expression.register(ogAST.PrimBoolean)
def _integer(primary): def _integer(primary):
''' Generate code for a raw integer/real/boolean value ''' ''' Generate code for a raw integer/real/boolean value '''
pass pass
@generate.register(ogAST.PrimEmptyString) @expression.register(ogAST.PrimEmptyString)
def _empty_string(primary): def _empty_string(primary):
''' Generate code for an empty SEQUENCE OF: {} ''' ''' Generate code for an empty SEQUENCE OF: {} '''
pass pass
@generate.register(ogAST.PrimStringLiteral) @expression.register(ogAST.PrimStringLiteral)
def _string_literal(primary): def _string_literal(primary):
''' Generate code for a string (Octet String) ''' ''' Generate code for a string (Octet String) '''
pass pass
@generate.register(ogAST.PrimConstant) @expression.register(ogAST.PrimConstant)
def _constant(primary): def _constant(primary):
''' Generate code for a reference to an ASN.1 constant ''' ''' Generate code for a reference to an ASN.1 constant '''
pass pass
@generate.register(ogAST.PrimMantissaBaseExp) @expression.register(ogAST.PrimMantissaBaseExp)
def _mantissa_base_exp(primary): def _mantissa_base_exp(primary):
''' Generate code for a Real with Mantissa-base-Exponent representation ''' ''' Generate code for a Real with Mantissa-base-Exponent representation '''
pass pass
@generate.register(ogAST.PrimIfThenElse) @expression.register(ogAST.PrimIfThenElse)
def _if_then_else(ifThenElse): def _if_then_else(ifThenElse):
''' Return string and statements for ternary operator ''' ''' Return string and statements for ternary operator '''
pass pass
@generate.register(ogAST.PrimSequence) @expression.register(ogAST.PrimSequence)
def _sequence(seq): def _sequence(seq):
''' Return Ada string for an ASN.1 SEQUENCE ''' ''' Return string for an ASN.1 SEQUENCE '''
pass pass
@generate.register(ogAST.PrimSequenceOf) @expression.register(ogAST.PrimSequenceOf)
def _sequence_of(seqof): def _sequence_of(seqof):
''' Return Ada string for an ASN.1 SEQUENCE OF ''' ''' Return string for an ASN.1 SEQUENCE OF '''
pass pass
@generate.register(ogAST.PrimChoiceItem) @expression.register(ogAST.PrimChoiceItem)
def _choiceitem(choice): def _choiceitem(choice):
''' Return the Ada code for a CHOICE expression ''' ''' Return the code for a CHOICE expression '''
pass
@generate.register(ogAST.Decision)
def _decision(dec):
''' generate the code for a decision '''
pass
@generate.register(ogAST.Label)
def _label(tr):
''' Transition following labels are generated in a separate section
for visibility reasons (see Ada scope)
'''
pass pass
@generate.register(ogAST.Transition)
def _transition(tr):
''' generate the code for a transition '''
pass
@generate.register(ogAST.Floating_label)
def _floating_label(label):
''' Generate the code for a floating label (Ada label + transition) '''
pass
@generate.register(ogAST.Procedure)
def _inner_procedure(proc):
''' Generate the code for a procedure '''
pass
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
flatten(ast) : transform a model with nested states to a flat model flatten(ast) : transform a model with nested states to a flat model
rename_everything(ast, from_name, to_name) : rename symbols rename_everything(ast, from_name, to_name) : rename symbols
inner_labels_to_floating(process) : remove labels from transitions
Copyright (c) 2012-2014 European Space Agency Copyright (c) 2012-2014 European Space Agency
...@@ -43,7 +44,7 @@ def inner_labels_to_floating(process): ...@@ -43,7 +44,7 @@ def inner_labels_to_floating(process):
for new_floating in find_labels(proc_tr): for new_floating in find_labels(proc_tr):
process.content.floating_labels.append(new_floating) process.content.floating_labels.append(new_floating)
for new_floating in find_labels(process.content.start.transition): for new_floating in find_labels(process.content.start.transition):
process.content.floating_labels.append(new_floating) process.content.floating_labels.append(new_floating)
for each in process.content.named_start: for each in process.content.named_start:
for new_floating in find_labels(each.transition): for new_floating in find_labels(each.transition):
process.content.floating_labels.append(new_floating) process.content.floating_labels.append(new_floating)
...@@ -53,7 +54,7 @@ def flatten(process): ...@@ -53,7 +54,7 @@ def flatten(process):
''' Flatten the nested states: ''' Flatten the nested states:
Rename inner states, procedures, etc. and move them to process level Rename inner states, procedures, etc. and move them to process level
''' '''
def update_terminator(context, term, process): def update_terminator(context, term):
'''Set next_id, identifying the next transition to run ''' '''Set next_id, identifying the next transition to run '''
if term.inputString.lower() in (st.statename.lower() if term.inputString.lower() in (st.statename.lower()
for st in context.composite_states): for st in context.composite_states):
...@@ -124,7 +125,7 @@ def flatten(process): ...@@ -124,7 +125,7 @@ def flatten(process):
if each.kind == 'next_state': if each.kind == 'next_state':
each.inputString = prefix + each.inputString each.inputString = prefix + each.inputString
# Set next transition id # Set next transition id
update_terminator(state, each, process) update_terminator(state, each)
elif each.kind == 'join': elif each.kind == 'join':
rename_everything(state.content, rename_everything(state.content,
each.inputString, each.inputString,
...@@ -167,7 +168,7 @@ def flatten(process): ...@@ -167,7 +168,7 @@ def flatten(process):
# Update terminators at process level # Update terminators at process level
for each in process.terminators: for each in process.terminators:
if each.kind == 'next_state': if each.kind == 'next_state':
update_terminator(process, each, process) update_terminator(process, each)
@singledispatch @singledispatch
......
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