Commits (3)
......@@ -124,6 +124,10 @@ The background pattern was downloaded from www.subtlepatterns.com
Changelog
=========
**3.5.1 (04/2021)**
- Support aliases:
dcl var type renames foo.bar.baz;
**3.5.0 (04/2021)**
- Support Input/Ouput expressions for model checkers
......
......@@ -328,7 +328,15 @@ LD_LIBRARY_PATH=./lib:.:$LD_LIBRARY_PATH opengeode-simulator
# generate the lookup tables for the state machine runtime
mapping = Helper.map_input_state(process)
VARIABLES.update(process.variables)
for (var_name, content) in process.variables.items():
# filter out the aliases and put them in the local variable pool
# to avoid unwanted prefixes when using them
if var_name in process.aliases.keys():
LOCAL_VAR[var_name] = content
else:
VARIABLES[var_name] = content
#VARIABLES.update(process.variables)
MONITORS.update(process.monitors)
process_level_decl = []
......@@ -402,6 +410,8 @@ LD_LIBRARY_PATH=./lib:.:$LD_LIBRARY_PATH opengeode-simulator
context_elems.append(f'{each.statename.lower()}{SEPARATOR}state {process_asn1}-States')
for var_name, (var_type, def_value) in process.variables.items():
if var_name in process.aliases.keys():
continue
context_elems.append(f'{var_name.lower()} {type_name(var_type, False)}')
asn1_context = (f'\n{process_asn1}-Context ::='' SEQUENCE {\n'
......@@ -460,6 +470,9 @@ LD_LIBRARY_PATH=./lib:.:$LD_LIBRARY_PATH opengeode-simulator
initial_values = []
# some parts of the context may have initial values
for var_name, (var_type, def_value) in process.variables.items():
if var_name in process.aliases.keys():
# aliases are not part of the context
continue
if def_value:
# Expression must be a ground expression, i.e. must not
# require temporary variable to store computed result
......@@ -478,11 +491,18 @@ LD_LIBRARY_PATH=./lib:.:$LD_LIBRARY_PATH opengeode-simulator
ctxt += "others => <>);"
context_decl.append(ctxt)
# Add monitors, that are pointers that must be set by an external
# Add monitors, that are variables that must be set by an external
# module. They are not part of the global state of the process, and
# are used by observer functions to read/write the system state
# We don't use pointers because that is incompatible with aliases
for mon_name, (mon_type, _) in process.monitors.items():
context_decl.append(f"{mon_name} : access {type_name(mon_type)};")
context_decl.append(f"{mon_name} : {type_name(mon_type)};")
# Add aliases
for alias_name, (alias_sort, alias_expr) in process.aliases.items():
_, qualified, _ = expression(alias_expr)
context_decl.append(f"{alias_name} : {type_name(alias_sort)} "
f"renames {qualified};")
# The choice selections will allow to use the present operator
# together with a variable of the -selection type
......@@ -1751,8 +1771,9 @@ def _primary_variable(prim, **kwargs):
ada_string = f'{sep}{prim.value[0]}'
if find_monitoring(prim.value[0]):
ada_string += ".all"
# Removed: we do not use access types for monitorings
#if find_monitoring(prim.value[0]):
# ada_string += ".all"
return [], str(ada_string), []
......
This diff is collapsed.
......@@ -886,6 +886,14 @@ class Process:
self.global_variables = {}
self.global_monitors = {}
self.global_timers = []
# aliases allow to access deep structures fields with a shorter syntax
# the _ast version is a temporary storage of the antlr parse tree. The actual
# processed entry is created from it after all actual variables from all
# text areas have been parsed, to be able to check the type of the alias
# format of the _ast: list of tuple (variable name, asn1 sort, ANTLR ast, ogAST.Text_Area)
self._aliases_ast = []
# format: {'alias_name': (asn1 sort, ogAST.Expression)
self.aliases = {}
# Set default coordinates and width/height
self.pos_x = 250
self.pos_y = 150
......
......@@ -2707,13 +2707,16 @@ def variables(root, ta_ast, context, monitor=False):
"monitors" dictionary of the context, instead of the
variables. this is for use in the context of observers
for model checking.
'''
variable can be defined as an alias to a field of a structure,
in that case the syntax is "dcl variable type renames path.to.field;"
'''
var = []
errors = []
warnings = []
asn1_sort, def_value = UNKNOWN_TYPE, None
for child in root.getChildren():
if child.type == lexer.ID:
renames = False
var.append(child.text)
elif child.type == lexer.SORT:
sort = child.getChild(0).text
......@@ -2722,6 +2725,11 @@ def variables(root, ta_ast, context, monitor=False):
asn1_sort = sdl_to_asn1(sort)
except TypeError as err:
errors.append(error(root, str(err)))
elif child.type == lexer.RENAMES:
if monitor:
errors.append(f'{var[-1]}: aliasing on monitors is not allowed')
else:
context._aliases_ast.append((var[-1], asn1_sort, child.getChild(0), ta_ast))
elif child.type == lexer.GROUND:
# Default value for a variable - needs to be a ground expression
def_value, err, warn = expression(child.getChild(0), context)
......@@ -2765,6 +2773,8 @@ def variables(root, ta_ast, context, monitor=False):
warnings.append('Unsupported variables construct type: ' +
str(child.type))
for variable in var:
# note: aliases are added to the variables list. code generator have
# to be careful to make the link with the actual field
if not hasattr(context, 'variables'):
errors.append('Variables/monitors shall not be declared here')
# Add to the context and text area AST entries
......@@ -2784,7 +2794,7 @@ def variables(root, ta_ast, context, monitor=False):
context.monitors[variable.lower()] = (asn1_sort, def_value)
ta_ast.monitors[variable.lower()] = (asn1_sort, def_value)
if not DV:
errors.append('Cannot do semantic checks on variable declarations')
errors.append('No visible dataview to make semantic checks on variable declarations')
return errors, warnings
......@@ -3922,6 +3932,25 @@ def process_definition(root, parent=None, context=None):
err, warn = procedure_post(proc, content, context=process)
errors.extend(err)
warnings.extend(warn)
# once all text areas have been parsed, we must parse the aliases
# (e.g. dcl variable type renames field.foo.bar). this could not be done
# before all regular DCL/Monitor variables were parsed.
for (alias_name, alias_sort, alias_ast, ta_ast) in process._aliases_ast:
expr, err, warn = expression(alias_ast, context=process)
for each in err:
errors.append([f"In alias '{alias_name}': {each}",
[ta_ast.pos_x or 0, ta_ast.pos_y or 0], []])
for each in warn:
warnings.append([f"In alias '{alias_name}': {each}",
[ta_ast.pos_x or 0, ta_ast.pos_y or 0], []])
t1 = type_name(alias_sort)
t2 = type_name(expr.exprType)
if t1 != t2:
errors.append([f"In alias '{alias_name}': type mismatch ({t1} vs {t2})",
[ta_ast.pos_x or 0, ta_ast.pos_y or 0], []])
else:
process.aliases[alias_name] = (alias_sort, expr)
if not process.referenced and not process.instance_of_name \
and (not process.content.start or
not process.content.start.terminators):
......
......@@ -141,7 +141,7 @@ except ImportError:
__all__ = ['opengeode', 'SDL_Scene', 'SDL_View', 'parse']
__version__ = '3.5.0'
__version__ = '3.5.1'
if hasattr(sys, 'frozen'):
# Detect if we are running on Windows (py2exe-generated)
......
This diff is collapsed.
This diff is collapsed.
......@@ -51,7 +51,7 @@ SDL_BLACKBOLD = ['\\b{word}\\b'.format(word=word) for word in (
'SET_TIMER', 'RESET_TIMER', 'VIA', 'ENTRY', 'EXIT', 'PRIORITY',
'SYNTYPE', 'ENDSYNTYPE', 'CONSTANTS', 'ENDPROCEDURE', 'FOR',
'COMMENT', 'SIGNAL', 'SIGNALLIST', 'USE', 'RETURNS', 'ANY',
'EXPORTED', 'REFERENCED', 'MONITOR',
'EXPORTED', 'REFERENCED', 'MONITOR', 'RENAMES',
'NEWTYPE', 'ENDNEWTYPE', 'ARRAY', 'STRUCT', 'SYNONYM')]
SDL_REDBOLD = ['\\b{word}\\b'.format(word=word) for word in (
......
......@@ -96,6 +96,7 @@ tokens {
PROVIDED;
QUESTION;
RANGE;
RENAMES;
RESET;
RETURN;
RETURNS;
......@@ -418,6 +419,9 @@ field_definition
;
/* variable definition has one extension to SDL: it is possible to specify
an alias to a data structure element:
dcl variable type renames foo.bar.baz */
variable_definition
: DCL variables_of_sort
(',' variables_of_sort)*
......@@ -453,8 +457,10 @@ synonym_definition_item
variables_of_sort
: variable_id (',' variable_id)* sort (':=' ground_expression)?
-> ^(VARIABLES variable_id+ sort ground_expression?)
: variable_id (',' variable_id)* sort
((':=' ground_expression) | (RENAMES variable))?
-> ^(VARIABLES variable_id+ sort
ground_expression? ^(RENAMES variable)?)
;
......@@ -1508,6 +1514,7 @@ DASH : '-';
ANY : A N Y;
ASTERISK : '*';
DCL : D C L;
RENAMES : R E N A M E S;
MONITOR : M O N I T O R;
END : E N D;
KEEP : K E E P;
......