Commit 09470961 authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Add support for x := CALL Procedure in TASK symbol

standard SDL syntax. Also works with parameterless procedures
parent e66abb9a
......@@ -112,6 +112,10 @@ The background pattern was downloaded from www.subtlepatterns.com
Changelog
=========
3.0.5 (06/2020)
- Add support to standard SDL syntax x := CALL procedure
in tasks
3.0.4 (06/2020)
- Fix use of ASN.1 constants in decision branches
......
......@@ -1880,18 +1880,17 @@ def _prim_call(prim, **kwargs):
local_decl.append('package Math is new '
'Ada.Numerics.Generic_Elementary_Functions'
'(Asn1Real);')
ada_string += "Math.Sqrt({})".format(param_str)
ada_string += f"Math.Sqrt({param_str})"
elif ident == 'trunc':
exp = params[0]
exp_typename = type_name(exp.exprType)
param_stmts, param_str, local_var = expression(exp, readonly=1)
stmts.extend(param_stmts)
local_decl.extend(local_var)
ada_string += "{sort}'Truncation({p})".format(sort=exp_typename,
p=param_str)
ada_string += f"{exp_typename}'Truncation({param_str})"
else:
# inner procedure call (with a RETURN statement)
ada_string += u'p{}{}('.format(SEPARATOR, ident)
ada_string += f'p{SEPARATOR}{ident}' + (' (' if params else '')
# Take all params and join them with commas
list_of_params = []
for param in params:
......@@ -1900,7 +1899,7 @@ def _prim_call(prim, **kwargs):
stmts.extend(param_stmt)
local_decl.extend(local_var)
ada_string += ', '.join(list_of_params)
ada_string += ')'
ada_string += ')' if params else ''
return stmts, str(ada_string), local_decl
......
This diff is collapsed.
......@@ -40,7 +40,7 @@ from collections import defaultdict
LOG = logging.getLogger(__name__)
class Expression(object):
class Expression:
''' AST Entry for expressions - Always use subtype '''
is_raw = False
......@@ -316,7 +316,7 @@ class PrimSequence(Primary):
pass
class Decision(object):
class Decision:
''' AST Entry for a decision '''
def __init__(self):
''' A DECISION statement '''
......@@ -347,7 +347,7 @@ class Decision(object):
l=self.line, c=self.charPositionInLine)
class Answer(object):
class Answer:
''' AST Entry for a decision answer '''
def __init__(self):
''' One ANSWER of a DECISION '''
......@@ -381,7 +381,7 @@ class Answer(object):
l=self.line, c=self.charPositionInLine)
class Task(object):
class Task:
''' AST Entry for TASKS '''
def __init__(self):
''' Initialize TASK attributes (set of ASSIGN statements) '''
......@@ -422,7 +422,7 @@ class TaskForLoop(Task):
pass
class Output(object):
class Output:
''' AST Entry for OUTPUT statements '''
def __init__(self, defName=''):
''' Set of OUTPUT statements '''
......@@ -446,11 +446,16 @@ class Output(object):
class ProcedureCall(Output):
''' Procedure calls content is identical to Outputs '''
pass
''' Procedure calls content is identical to Outputs
with exception that it may have a return type (exprType) '''
def __init__(self, defName=''):
super().__init__(defName)
# exprType is an ASN.1 type (as exported by asn1scc)
self.exprType = None
self.is_raw = False
class Terminator(object):
class Terminator:
''' Terminator elements (join, nextstate, stop, return) '''
def __init__(self, defName=''):
''' Initialize terminator attributes '''
......@@ -510,7 +515,7 @@ class Terminator(object):
x=self.pos_x, y=self.pos_y)
class Label(object):
class Label:
''' AST Entry for a Label '''
def __init__(self):
''' Initialize the label attributes '''
......@@ -559,7 +564,7 @@ class Floating_label(Label):
l=self.line, c=self.charPositionInLine)
class Transition(object):
class Transition:
''' AST Entry for a complete transition '''
def __init__(self):
''' Initialize the transition attributes '''
......@@ -584,7 +589,7 @@ class Transition(object):
return u'\n'.join(data)
class Input(object):
class Input:
''' AST Entry for the INPUT symbol '''
def __init__(self):
''' Initialize the Input attributes '''
......@@ -649,7 +654,7 @@ class ContinuousSignal(Input):
l=self.line, c=self.charPositionInLine)
class Start(object):
class Start:
''' AST Entry for the START symbol '''
def __init__(self):
''' Initialize the Start symbol attributes '''
......@@ -681,7 +686,7 @@ class CompositeState_start(Start):
pass
class Comment(object):
class Comment:
''' AST Entry for COMMENT symbols '''
def __init__(self):
''' Comment symbol '''
......@@ -703,7 +708,7 @@ class Comment(object):
l=self.line, c=self.charPositionInLine)
class State(object):
class State:
''' AST Entry for STATE symbols '''
def __init__(self, defName=''):
''' Used only for rendering backends - not for code generation '''
......@@ -740,7 +745,7 @@ class State(object):
x=self.pos_x, y=self.pos_y)
class TextArea(object):
class TextArea:
''' AST Entry for text areas (containing declarations/comments) '''
def __init__(self):
''' Text area (raw content for rendering only) '''
......@@ -773,7 +778,7 @@ class TextArea(object):
l=self.line, c=self.charPositionInLine)
class Automaton(object):
class Automaton:
''' Elements contained in a process, procedure or composite state'''
def __init__(self, parent=None):
''' AST grouping the elements that can be rendered graphically '''
......@@ -786,7 +791,7 @@ class Automaton(object):
self.named_start = []
class Procedure(object):
class Procedure:
''' Internal procedure definition '''
def __init__(self):
''' Procedure AST default value '''
......@@ -842,7 +847,7 @@ class Procedure(object):
self.output_signals = []
class Process(object):
class Process:
''' SDL Process entry point '''
def __init__(self):
''' Process AST default values '''
......@@ -974,7 +979,7 @@ class StateAggregation(CompositeState):
l=self.line, c=self.charPositionInLine)
class Block(object):
class Block:
''' AST for a BLOCK entity '''
def __init__(self):
'''
......@@ -1005,7 +1010,7 @@ class Block(object):
self.fpar = []
class System(object):
class System:
''' AST for a SYSTEM entity '''
def __init__(self):
'''
......@@ -1030,7 +1035,7 @@ class System(object):
self.text_areas = []
class AST(object):
class AST:
''' Top-level AST entry point '''
def __init__(self):
'''
......
......@@ -43,7 +43,7 @@ import antlr3
from antlr3 import tree
from . import sdl92Lexer as lexer
from .sdl92Parser import sdl92Parser
from . import sdl92Parser
from . import ogAST
from .Asn1scc import parse_asn1, ASN1, create_choice_determinant_types
......@@ -1580,6 +1580,20 @@ def expression(root, context, pos='right'):
return call_expression(root, context)
elif root.type == lexer.SELECTOR:
return selector_expression(root, context, pos)
elif root.type == lexer.PROCEDURE_CALL:
pc, err, warn = procedure_call(root, parent=None, context=context)
# when used as an expression, the error coordinates must be stripped
# as they are set for standalone PROCEDURE CALL symbols
errs = [each[0] for each in err]
warns = [each[0] for each in warn]
# Transform the into a PrimCall
prim = ogAST.PrimCall()
prim.exprType = pc.exprType
prim.inputString = pc.inputString
prim.tmpVar = tmp()
prim.value = [pc.output[0]['outputName'],
{'procParams': pc.output[0]['params']}]
return prim, errs, warns
else:
raise NotImplementedError(sdl92Parser.tokenNamesMap[root.type] +
' - line ' + str(root.getLine()))
......@@ -3475,7 +3489,7 @@ def process_definition(root, parent=None, context=None):
proc_x, proc_y = 0, 0
inner_proc = []
# first look for all text areas to find type declarations
# first look for all text areas to find NEWTYPE declarations
USER_DEFINED_TYPES.clear()
tas = (x for x in root.getChildren() if x.type == lexer.TEXTAREA)
for child in tas:
......@@ -3489,6 +3503,25 @@ def process_definition(root, parent=None, context=None):
# we just need the types to be visible
_, _ = newtype(sort, None, context)
# then parse procedures, so that their signature is set in the ast
procedures = (x for x in root.getChildren() if x.type == lexer.PROCEDURE)
for child in procedures:
proc, content, err, warn = procedure_pre(
child, parent=None, context=process)
inner_proc.append((proc, content))
errors.extend(err)
warnings.extend(warn)
# check for duplicate declaration
if any(each.inputString.lower() == proc.inputString.lower()
for each in chain(process.content.inner_procedures,
process.procedures)):
errors.append(['Duplicate Procedure declaration: {}'
.format(proc.inputString),
[proc.pos_x, proc.pos_y], []])
# Add it at process level so that it is in the scope
process.content.inner_procedures.append(proc)
process.procedures.append(proc)
# Prepare the transition/state mapping
process.mapping = {name: [] for name in get_state_list(root)}
process.cs_mapping = {name: [] for name in get_state_list(root)}
......@@ -3548,21 +3581,7 @@ def process_definition(root, parent=None, context=None):
warnings.extend(warn)
process.fpar = params
elif child.type == lexer.PROCEDURE:
proc, content, err, warn = procedure_pre(
child, parent=None, context=process)
inner_proc.append((proc, content))
errors.extend(err)
warnings.extend(warn)
# check for duplicate declaration
if any(each.inputString.lower() == proc.inputString.lower()
for each in chain(process.content.inner_procedures,
process.procedures)):
errors.append(['Duplicate Procedure declaration: {}'
.format(proc.inputString),
[proc.pos_x, proc.pos_y], []])
# Add it at process level so that it is in the scope
process.content.inner_procedures.append(proc)
process.procedures.append(proc)
continue
elif child.type == lexer.FLOATING_LABEL:
lab, err, warn = floating_label(
child, parent=None, context=process)
......@@ -4106,11 +4125,19 @@ def end(root, parent=None, context=None):
return c, [], []
def procedure_call(root, parent, context):
''' Parse a PROCEDURE CALL (synchronous required interface) '''
# Same as OUTPUT for external procedures
def procedure_call(root: antlr3.tree.CommonTree,
parent,
context: ogAST.Process):
''' Parse a PROCEDURE CALL '''
out_ast = ogAST.ProcedureCall()
_, err, warn = output(root, parent, out_ast, context)
# Check if the procedure exists, and assign an exprType to
# the procedure call in case it has a Return statement
call_name = out_ast.output[0]['outputName'].lower()
for each in context.procedures:
if each.inputString.lower() == call_name:
out_ast.exprType = each.return_type
break
return out_ast, err, warn
......@@ -5424,7 +5451,7 @@ def parser_init(filename=None, string=None):
raise IOError('String parsing error: ' + str(err))
lex = lexer.sdl92Lexer(char_stream)
tokens = antlr3.CommonTokenStream(lex)
parser = sdl92Parser(tokens)
parser = sdl92Parser.sdl92Parser(tokens)
# bug in the antlr3.5 runtime for python3 - attribute "error_list"
# is missing - we have to add it manually here
parser.error_list=[]
......
......@@ -140,7 +140,7 @@ except ImportError:
__all__ = ['opengeode', 'SDL_Scene', 'SDL_View', 'parse']
__version__ = '3.0.4'
__version__ = '3.0.5'
if hasattr(sys, 'frozen'):
# Detect if we are running on Windows (py2exe-generated)
......
This diff is collapsed.
This diff is collapsed.
......@@ -1055,7 +1055,8 @@ unary_expression
: postfix_expression
| primary_expression
| NOT^ unary_expression
| DASH unary_expression -> ^(NEG unary_expression)
| DASH unary_expression -> ^(NEG unary_expression)
| CALL procedure_call_body -> ^(PROCEDURE_CALL procedure_call_body)
;
......
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