Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
OpenGEODE
Commits
67073155
Commit
67073155
authored
Mar 28, 2021
by
Maxime Perrotin
Browse files
Add support for synchronous PIs (exported procedures)
parent
baef5f9e
Changes
10
Expand all
Show whitespace changes
Inline
Side-by-side
README.md
View file @
67073155
...
...
@@ -124,6 +124,9 @@ The background pattern was downloaded from www.subtlepatterns.com
Changelog
=========
**3.4.0 (03/2021)**
-
Support exported/reference procedures (allowing remote synchronous calls)
**3.3.7 (03/2021)**
-
Support IA5String type
...
...
opengeode/AdaGenerator.py
View file @
67073155
...
...
@@ -712,8 +712,13 @@ package body {process_name}_RI is''']
pi_header
=
procedure_header
(
proc
)
ads_template
.
append
(
f
'
{
pi_header
}
;'
)
if
not
proc
.
external
and
not
generic
:
if
not
proc
.
exported
:
ads_template
.
append
(
f
'pragma Export (C, p
{
SEPARATOR
}{
proc
.
inputString
}
, "_
{
proc
.
inputString
}
");'
)
else
:
# Export for TASTE as a synchronous PI
ads_template
.
append
(
f
'pragma Export (C, p
{
SEPARATOR
}{
proc
.
inputString
}
, "
{
process_name
.
lower
()
}
_PI_
{
proc
.
inputString
}
");'
)
# Generate the code for the process-level variable declarations
taste_template
.
extend
(
process_level_decl
)
...
...
opengeode/Renderer.py
View file @
67073155
...
...
@@ -126,7 +126,7 @@ def _automaton(ast, scene):
top_level_symbols
.
extend
(
[
render
(
proc
,
scene
)
for
proc
in
ast
.
inner_procedures
if
not
proc
.
external
])
if
not
proc
.
external
and
not
proc
.
textual_procedure
])
# Render the start symbol
if
ast
.
start
:
...
...
opengeode/ogAST.py
View file @
67073155
...
...
@@ -842,6 +842,8 @@ class Procedure:
self
.
external
=
False
# Determine if a procedure is a remote procedure
self
.
exported
=
False
# Determine if a procedure only has a textual definition
self
.
textual_procedure
=
False
# Optional comment
self
.
comment
=
None
# Set of symbols contained in the procedure (type Automaton)
...
...
@@ -851,6 +853,10 @@ class Procedure:
self
.
output_signals
=
[]
# The "DECISION ANY" construct requires random number generators
self
.
random_generator
=
set
()
# Procedure declared as EXPORTED
self
.
exported
:
bool
=
False
# procedure declared as REFERENCED
self
.
referenced
:
bool
=
False
class
Process
:
...
...
@@ -1032,6 +1038,7 @@ class System:
self
.
filename
=
None
# Reference to top-level AST
self
.
ast
=
None
# self.parent = None
# list of SIGNAL declarations: [{'name': str, 'type': asn1type}]
# (Supporting only one parameter)
self
.
signals
=
[]
...
...
@@ -1051,6 +1058,8 @@ class AST:
AST entries are systems, processes, and USE clauses
(cf. ANTLR grammar, production "pr_file")
'''
# Top-level node: parent remains None
self
.
parent
=
None
# Set of input files the AST was created from
self
.
pr_files
=
set
()
# USE clauses: list of strings (eg. "DataView")
...
...
opengeode/ogParser.py
View file @
67073155
...
...
@@ -2813,13 +2813,10 @@ def composite_state(root, parent=None, context=None):
elif
new_proc
.
inputString
.
strip
().
lower
()
==
'exit'
:
comp
.
exit_procedure
=
new_proc
# check for duplicate declaration
if
any
(
each
.
inputString
.
lower
()
==
new_proc
.
inputString
.
lower
()
for
each
in
chain
(
comp
.
content
.
inner_procedures
,
context
.
procedures
)
if
each
.
inputString
.
lower
()
not
in
(
'entry'
,
'exit'
)):
errors
.
append
([
'Duplicate procedure Declaration: {}'
.
format
(
new_proc
.
inputString
),
[
new_proc
.
pos_x
,
new_proc
.
pos_y
],
[]])
dupl_errs
=
[]
check_duplicate_procedures
(
comp
,
new_proc
,
dupl_errs
)
for
err_str
in
dupl_errs
:
errors
.
append
([
err_str
,
[
new_proc
.
pos_x
,
new_proc
.
pos_y
],
[]])
# Add procedure to the context, to make it visible at scope level
comp
.
content
.
inner_procedures
.
append
(
new_proc
)
context
.
procedures
.
append
(
new_proc
)
...
...
@@ -2968,6 +2965,10 @@ def procedure_pre(root, parent=None, context=None):
elif
child
.
type
in
(
lexer
.
PROCEDURE
,
lexer
.
START
,
lexer
.
STATE
,
lexer
.
FLOATING_LABEL
):
content
.
append
(
child
)
elif
child
.
type
==
lexer
.
EXPORTED
:
proc
.
exported
=
True
elif
child
.
type
==
lexer
.
REFERENCED
:
proc
.
referenced
=
True
else
:
warnings
.
append
([
'Unsupported construct in procedure, type: '
+
...
...
@@ -2987,6 +2988,51 @@ def procedure_returns(root):
return
sdl_to_asn1
(
root
.
getChild
(
1
).
getChild
(
0
).
text
),
\
root
.
getChild
(
0
).
text
def
check_duplicate_procedures
(
ctxt
,
proc
,
errors
=
[]):
''' Check for duplicates procedure declarations in a given context
and recursively in contexts above
If the proceduure in the context is declared as referenced,
then report an error only if the signature is different
Procedure named "entry" and "exit" are ignored
'''
name
=
proc
.
inputString
.
lower
()
if
not
isinstance
(
ctxt
,
ogAST
.
System
)
and
ctxt
.
parent
!=
None
:
check_duplicate_procedures
(
ctxt
.
parent
,
proc
,
errors
)
if
isinstance
(
ctxt
,
ogAST
.
AST
):
# If we are at AST top level there are no declarations -> ignore
return
if
name
in
(
'entry'
,
'exit'
):
# ignore special entry/exit procedures
return
try
:
content
=
ctxt
.
content
.
inner_procedures
except
AttributeError
:
content
=
[]
for
each
in
chain
(
content
,
ctxt
.
procedures
):
if
each
.
inputString
.
lower
()
==
name
:
if
not
each
.
referenced
and
not
proc
.
referenced
:
errors
.
append
(
'Duplicate procedure declaration: {}'
.
format
(
name
))
else
:
mismatch
=
False
# at least one is referenced -> compare signatures
left
,
right
=
proc
.
fpar
,
each
.
fpar
if
len
(
left
)
!=
len
(
right
):
mismatch
=
True
for
idx
,
val
in
enumerate
(
left
):
if
(
right
[
idx
][
'name'
]
!=
val
[
'name'
]
or
type_name
(
right
[
idx
][
'type'
])
!=
type_name
(
val
[
'type'
])
or
right
[
idx
][
'direction'
]
!=
val
[
'direction'
]):
mismatch
=
True
break
if
mismatch
:
errors
.
append
(
f
'Procedure
{
proc
.
inputString
}
: '
'declaration and definition interface mismatch'
)
if
proc
.
exported
!=
each
.
exported
:
# If declared exported, definition must be exported too
# Setting the flag here, this will ease code generators
proc
.
exported
=
each
.
exported
=
True
def
procedure_post
(
proc
,
content
,
parent
=
None
,
context
=
None
):
''' Parse the content of a procedure '''
...
...
@@ -3016,16 +3062,13 @@ def procedure_post(proc, content, parent=None, context=None):
errors
.
extend
(
err
)
warnings
.
extend
(
warn
)
# check for duplicate declaration
err
=
any
(
each
.
inputString
.
lower
()
==
new_proc
.
inputString
.
lower
()
for
each
in
chain
(
proc
.
content
.
inner_procedures
,
context
.
procedures
))
dupl_errs
=
[]
check_duplicate_procedures
(
context
,
new_proc
,
dupl_errs
)
# Add procedure to the context, to make it visible at scope level
context
.
procedures
.
append
(
new_proc
)
proc
.
content
.
inner_procedures
.
append
(
new_proc
)
if
err
:
errors
.
append
([
'Duplicate declaration of procedure {}'
.
format
(
new_proc
.
inputString
),
[
0
,
0
],
[]])
for
err_str
in
dupl_errs
:
errors
.
append
([
err_str
,
[
0
,
0
],
[]])
elif
child
.
type
==
lexer
.
START
:
# START transition (fills the mapping structure)
proc
.
content
.
start
,
err
,
warn
=
start
(
child
,
context
=
proc
)
...
...
@@ -3369,6 +3412,8 @@ def text_area_content(root, ta_ast, context):
for
each
in
procedures
:
# Procedure textual declarations need ASN.1 types
proc
,
err
,
warn
=
procedure
(
each
,
context
=
context
)
# set the flag to avoid rendering a graphical procedure
proc
.
textual_procedure
=
True
errors
.
extend
(
err
)
warnings
.
extend
(
warn
)
try
:
...
...
@@ -3376,12 +3421,7 @@ def text_area_content(root, ta_ast, context):
except
AttributeError
:
# May not be any content in current context (eg System)
content
=
[]
# check for duplicates
if
any
(
each
.
inputString
.
lower
()
==
proc
.
inputString
.
lower
()
for
each
in
chain
(
content
,
context
.
procedures
)):
errors
.
append
(
'Duplicate Procedure Declaration: {}'
.
format
(
proc
.
inputString
))
check_duplicate_procedures
(
context
,
proc
,
errors
)
# Add procedure to the container (process or procedure) if any
content
.
append
(
proc
)
# Add to context to make it visible at scope level
...
...
@@ -3546,6 +3586,7 @@ def system_definition(root, parent):
# Store the name of the file where the system is defined
system
.
filename
=
node_filename
(
root
)
system
.
ast
=
parent
#system.parent = parent
asn1_files
=
[]
signals
,
procedures
,
blocks
=
[],
[],
[]
for
child
in
root
.
getChildren
():
...
...
@@ -3571,7 +3612,7 @@ def system_definition(root, parent):
# Update list of ASN.1 files - if any
if
not
asn1_files
:
asn1_files
=
textarea
.
asn1_files
els
e
:
el
if
textarea
.
asn1_file
s
:
errors
.
append
(
'ASN.1 Files must be set in a single text area'
)
errors
.
extend
(
err
)
warnings
.
extend
(
warn
)
...
...
@@ -3598,6 +3639,8 @@ def system_definition(root, parent):
for
each
in
procedures
:
proc
,
err
,
warn
=
procedure
(
each
,
parent
=
None
,
context
=
system
)
# Procedure defined at system level are only textual
proc
.
textual_procedure
=
True
errors
.
extend
(
err
)
warnings
.
extend
(
warn
)
system
.
procedures
.
append
(
proc
)
...
...
@@ -3641,12 +3684,10 @@ def process_definition(root, parent=None, context=None):
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
],
[]])
dupl_errs
=
[]
check_duplicate_procedures
(
process
,
proc
,
dupl_errs
)
for
err_str
in
dupl_errs
:
errors
.
append
([
err_str
,
[
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
)
...
...
opengeode/opengeode.py
View file @
67073155
...
...
@@ -141,7 +141,7 @@ except ImportError:
__all__
=
[
'opengeode'
,
'SDL_Scene'
,
'SDL_View'
,
'parse'
]
__version__
=
'3.
3.8
'
__version__
=
'3.
4.0
'
if
hasattr
(
sys
,
'frozen'
):
# Detect if we are running on Windows (py2exe-generated)
...
...
opengeode/sdl92Lexer.py
View file @
67073155
This diff is collapsed.
Click to expand it.
opengeode/sdl92Parser.py
View file @
67073155
This diff is collapsed.
Click to expand it.
opengeode/sdlSymbols.py
View file @
67073155
...
...
@@ -51,6 +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'
,
'NEWTYPE'
,
'ENDNEWTYPE'
,
'ARRAY'
,
'STRUCT'
,
'SYNONYM'
)]
SDL_REDBOLD
=
[
'
\\
b{word}
\\
b'
.
format
(
word
=
word
)
for
word
in
(
...
...
sdl92.g
View file @
67073155
...
...
@@ -284,16 +284,19 @@ parameters_of_sort
// procedure
// 2021-03 Added EXPORTED and REFEERENCED keywords
// needed to declare a synchronous provided interface at system level
procedure
: cif?
PROCEDURE procedure_id (e1=end | SEMI)
EXPORTED?
PROCEDURE procedure_id (e1=end | SEMI)
fpar?
res=procedure_result?
(text_area | procedure)*
((processBody? ENDPROCEDURE procedure_id?) | EXTERNAL)
((processBody? ENDPROCEDURE procedure_id?)
| EXTERNAL | REFERENCED)
e2=end
-> ^(PROCEDURE cif? procedure_id $e1? $e2? fpar? $res?
text_area* procedure* processBody? EXTERNAL?)
text_area* procedure* processBody? EXTERNAL?
EXPORTED? REFERENCED?
)
;
// Procedure result / optional return type
...
...
@@ -1530,6 +1533,7 @@ DECISION : D E C I S I O N;
ENDDECISION : E N D D E C I S I O N;
EXPORT : E X P O R T;
EXTERNAL : E X T E R N A L;
EXPORTED : E X P O R T E D;
REFERENCED : R E F E R E N C E D;
CONNECTION : C O N N E C T I O N;
ENDCONNECTION : E N D C O N N E C T I O N;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment