Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
OpenGEODE
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
1
Issues
1
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
Operations
Operations
Incidents
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
TASTE
OpenGEODE
Commits
24924186
Commit
24924186
authored
Feb 28, 2014
by
Maxime Perrotin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adding project files
parent
11ed0fdb
Changes
117
Hide whitespace changes
Inline
Side-by-side
Showing
117 changed files
with
53124 additions
and
0 deletions
+53124
-0
AdaGenerator.py
AdaGenerator.py
+1448
-0
Clipboard.py
Clipboard.py
+178
-0
DataView.asn
DataView.asn
+23
-0
FONT-LICENCE.txt
FONT-LICENCE.txt
+96
-0
LICENSE
LICENSE
+165
-0
Lander.py
Lander.py
+265
-0
LlvmGenerator.py
LlvmGenerator.py
+1072
-0
MANIFEST.in
MANIFEST.in
+2
-0
Makefile
Makefile
+24
-0
README
README
+25
-0
Renderer.py
Renderer.py
+311
-0
Statechart.py
Statechart.py
+586
-0
__init__.py
__init__.py
+12
-0
compileGrammar.sh
compileGrammar.sh
+18
-0
design/behaviour.pr
design/behaviour.pr
+165
-0
dist.bat
dist.bat
+3
-0
fonts/Ubuntu-B.ttf
fonts/Ubuntu-B.ttf
+0
-0
fonts/Ubuntu-BI.ttf
fonts/Ubuntu-BI.ttf
+0
-0
fonts/Ubuntu-R.ttf
fonts/Ubuntu-R.ttf
+0
-0
fonts/Ubuntu-RI.ttf
fonts/Ubuntu-RI.ttf
+0
-0
generator.py
generator.py
+47
-0
generatorc.py
generatorc.py
+722
-0
genericSymbols.py
genericSymbols.py
+1642
-0
hyperlink.ui
hyperlink.ui
+81
-0
icons.py
icons.py
+21
-0
icons/ProcedureCall.svg
icons/ProcedureCall.svg
+103
-0
icons/ProcedureStart.svg
icons/ProcedureStart.svg
+181
-0
icons/ProcedureStop.svg
icons/ProcedureStop.svg
+212
-0
icons/comment.png
icons/comment.png
+0
-0
icons/comment.svg
icons/comment.svg
+94
-0
icons/condition.png
icons/condition.png
+0
-0
icons/decision.png
icons/decision.png
+0
-0
icons/decision.svg
icons/decision.svg
+99
-0
icons/decisionanswer.png
icons/decisionanswer.png
+0
-0
icons/decisionanswer.svg
icons/decisionanswer.svg
+121
-0
icons/input.png
icons/input.png
+0
-0
icons/input.svg
icons/input.svg
+89
-0
icons/join.png
icons/join.png
+0
-0
icons/join.svg
icons/join.svg
+202
-0
icons/label.png
icons/label.png
+0
-0
icons/label.svg
icons/label.svg
+158
-0
icons/og-logo-rocket-taste.svg
icons/og-logo-rocket-taste.svg
+367
-0
icons/og-logo.png
icons/og-logo.png
+0
-0
icons/og-logo.svg
icons/og-logo.svg
+274
-0
icons/og-rocket.png
icons/og-rocket.png
+0
-0
icons/opengeode.png
icons/opengeode.png
+0
-0
icons/output.png
icons/output.png
+0
-0
icons/output.svg
icons/output.svg
+106
-0
icons/procedure.png
icons/procedure.png
+0
-0
icons/procedure.svg
icons/procedure.svg
+117
-0
icons/procedurecall.png
icons/procedurecall.png
+0
-0
icons/procedurestart.png
icons/procedurestart.png
+0
-0
icons/procedurestop.png
icons/procedurestop.png
+0
-0
icons/start.png
icons/start.png
+0
-0
icons/start.svg
icons/start.svg
+65
-0
icons/startsvg.svg
icons/startsvg.svg
+65
-0
icons/state.png
icons/state.png
+0
-0
icons/state.svg
icons/state.svg
+68
-0
icons/task.png
icons/task.png
+0
-0
icons/task.svg
icons/task.svg
+91
-0
icons/textsymbol.png
icons/textsymbol.png
+0
-0
icons/texture.png
icons/texture.png
+0
-0
misc/lander.mp3
misc/lander.mp3
+0
-0
ogAST.py
ogAST.py
+788
-0
ogParser.py
ogParser.py
+2638
-0
opengeode.py
opengeode.py
+1706
-0
opengeode.qrc
opengeode.qrc
+27
-0
opengeode.ui
opengeode.ui
+268
-0
samnmax.py
samnmax.py
+75
-0
sdl92.g
sdl92.g
+1221
-0
sdl92Lexer.py
sdl92Lexer.py
+7130
-0
sdl92Parser.py
sdl92Parser.py
+23359
-0
sdlSymbols.py
sdlSymbols.py
+1048
-0
setup.py
setup.py
+36
-0
setup_windows.py
setup_windows.py
+20
-0
tests/regression/Makefile
tests/regression/Makefile
+14
-0
tests/regression/test1/DataView.py
tests/regression/test1/DataView.py
+38
-0
tests/regression/test1/Makefile
tests/regression/test1/Makefile
+18
-0
tests/regression/test1/dataview-uniq.asn
tests/regression/test1/dataview-uniq.asn
+17
-0
tests/regression/test1/og.pr
tests/regression/test1/og.pr
+151
-0
tests/regression/test1/system_structure.pr
tests/regression/test1/system_structure.pr
+28
-0
tests/regression/test2/DataView.py
tests/regression/test2/DataView.py
+904
-0
tests/regression/test2/Makefile
tests/regression/test2/Makefile
+17
-0
tests/regression/test2/dataview-uniq.asn
tests/regression/test2/dataview-uniq.asn
+678
-0
tests/regression/test2/orchestrator.pr
tests/regression/test2/orchestrator.pr
+118
-0
tests/regression/test2/system_structure.pr
tests/regression/test2/system_structure.pr
+58
-0
tests/regression/test3/DataView.py
tests/regression/test3/DataView.py
+495
-0
tests/regression/test3/Makefile
tests/regression/test3/Makefile
+18
-0
tests/regression/test3/dataview-uniq.asn
tests/regression/test3/dataview-uniq.asn
+125
-0
tests/regression/test3/fce.pr
tests/regression/test3/fce.pr
+459
-0
tests/regression/test3/system_structure.pr
tests/regression/test3/system_structure.pr
+69
-0
tests/regression/test4/DataView.py
tests/regression/test4/DataView.py
+294
-0
tests/regression/test4/Makefile
tests/regression/test4/Makefile
+18
-0
tests/regression/test4/dataview-uniq.asn
tests/regression/test4/dataview-uniq.asn
+54
-0
tests/regression/test4/orchestrator.pr
tests/regression/test4/orchestrator.pr
+236
-0
tests/regression/test4/system_structure.pr
tests/regression/test4/system_structure.pr
+36
-0
tests/regression/test5/DataView.py
tests/regression/test5/DataView.py
+26
-0
tests/regression/test5/Makefile
tests/regression/test5/Makefile
+18
-0
tests/regression/test5/dataview-uniq.asn
tests/regression/test5/dataview-uniq.asn
+9
-0
tests/regression/test5/function0.pr
tests/regression/test5/function0.pr
+42
-0
tests/regression/test5/system_structure.pr
tests/regression/test5/system_structure.pr
+36
-0
tests/regression/test6/DataView.py
tests/regression/test6/DataView.py
+138
-0
tests/regression/test6/Makefile
tests/regression/test6/Makefile
+19
-0
tests/regression/test6/dataview-uniq.asn
tests/regression/test6/dataview-uniq.asn
+47
-0
tests/regression/test6/myfunction.pr
tests/regression/test6/myfunction.pr
+46
-0
tests/regression/test6/system_structure.pr
tests/regression/test6/system_structure.pr
+28
-0
tests/regression/test7/DataView.py
tests/regression/test7/DataView.py
+228
-0
tests/regression/test7/Makefile
tests/regression/test7/Makefile
+19
-0
tests/regression/test7/dataview-uniq.asn
tests/regression/test7/dataview-uniq.asn
+90
-0
tests/regression/test7/orchestrator.pr
tests/regression/test7/orchestrator.pr
+243
-0
tests/regression/test7/system_structure.pr
tests/regression/test7/system_structure.pr
+48
-0
tests/regression/test8/DataView.py
tests/regression/test8/DataView.py
+228
-0
tests/regression/test8/Makefile
tests/regression/test8/Makefile
+18
-0
tests/regression/test8/dataview-uniq.asn
tests/regression/test8/dataview-uniq.asn
+90
-0
tests/regression/test8/orchestrator.pr
tests/regression/test8/orchestrator.pr
+40
-0
tests/regression/test8/system_structure.pr
tests/regression/test8/system_structure.pr
+48
-0
undoCommands.py
undoCommands.py
+184
-0
No files found.
AdaGenerator.py
0 → 100644
View file @
24924186
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
OpenGEODE - A tiny SDL Editor for TASTE
This module generates Ada code from SDL process models.
The Ada code is compliant with the TASTE interfaces, and is
using the ASN.1 "Space-Certified" compiler for data type definition.
(See TASTE documentation for more information)
The design is very flexible and can be used as basis for
generating other backends.
Entry point:
The AST of the model that is parsed is described in ogAST.py
A Visitor Pattern using Python's "singledispatch" mechanism is used
to go through the AST and generate code for each SDL construct.
There is a single function called "generate", decorated with the
singledispatch mechanism, that needs to be called to generate the code
of any AST element.
Most functions return two values: "code" and "local_decl", containing
a set of statements and a set of local variables (that can be later
placed anywhere in the code).
Functions corresponding to the AST entries that are related to
expressions return three values: "code", "ada_string" and "local_decl".
The additional "ada_string" value is the usable string that corresponds
to the result of the expression evaluation.
For example, take the SDL statement "OUTPUT hello(a+5)"
This results (in TASTE terminology) in calling the required interface
called "hello" and passing a parameter of an ASN.1 type (say MyInteger).
The parameter is always passed by reference.
It is therefore necessary to build a temporary variable to hold the result
of the "a+5" expression.
In this example, the "generate" function will return:
local_decl = ["tmp01 : MyInteger;"]
(The template backend can then place it wherever appropriate)
and code = ["tmp01 := a + 5;", "hello(tmp01);"]
(The template will then do a '
\n
'.join(code) - and add indents, etc.)
To know about "tmp01" and generate the code "hello(tmp01);",
the function will recursively call "generate" and
pass a+5 as parameter. The call will return the tuple:
local_decl = ["tmp01 : MyInteger;"]
code = ["tmp01 := a + 5;"]
ada_string = "tmp01"
This design allows to have any level of complexity in the embedded
expression in a way that is easy to handle (adding constructs with
this pattern is straightforward, once the generate function for each AST
entry is properly implemented).
Copyright (c) 2012-2013 European Space Agency
Designed and implemented by Maxime Perrotin
Contact: maxime.perrotin@esa.int
"""
import
logging
from
singledispatch
import
singledispatch
import
ogAST
LOG
=
logging
.
getLogger
(
__name__
)
__all__
=
[
'generate'
]
# reference to the ASN.1 Data view and to the visible variables (in scope)
TYPES
=
None
VARIABLES
=
{}
LOCAL_VAR
=
{}
# List of output signals and procedures
OUT_SIGNALS
=
[]
PROCEDURES
=
[]
INNER_PROCEDURES
=
[]
@
singledispatch
def
generate
(
ast
):
''' Generate the code for an item of the AST '''
raise
TypeError
(
'[AdaGenerator] Unsupported AST construct'
)
# Processing of the AST
@
generate
.
register
(
ogAST
.
Process
)
def
_process
(
process
):
''' Generate the code for a complete process (AST Top level) '''
process_name
=
process
.
processName
VARIABLES
.
update
(
process
.
variables
)
global
TYPES
TYPES
=
process
.
dataview
del
OUT_SIGNALS
[:]
del
PROCEDURES
[:]
del
INNER_PROCEDURES
[:]
OUT_SIGNALS
.
extend
(
process
.
output_signals
)
PROCEDURES
.
extend
(
process
.
procedures
)
INNER_PROCEDURES
.
extend
(
process
.
content
.
inner_procedures
)
LOG
.
info
(
'Generating Ada code for process '
+
str
(
process_name
))
# Generate the code to declare process-level variables
process_level_decl
=
[]
for
var_name
,
(
var_type
,
def_value
)
in
process
.
variables
.
viewitems
():
if
def_value
:
# Expression must be a ground expression, i.e. must not
# require temporary variable to store computed result
dst
,
dstr
,
dlocal
=
generate
(
def_value
)
assert
not
dst
and
not
dlocal
,
'DCL: Expecting a ground expression'
process_level_decl
.
append
(
'l_{n} : aliased asn1Scc{t}{default};'
.
format
(
n
=
var_name
,
t
=
var_type
.
ReferencedTypeName
.
replace
(
'-'
,
'_'
),
default
=
' := '
+
dstr
if
def_value
else
''
))
# Add the process states list to the process-level variables
states_decl
=
'type states is ('
states_decl
+=
', '
.
join
(
process
.
mapping
.
iterkeys
())
+
');'
process_level_decl
.
append
(
states_decl
)
process_level_decl
.
append
(
'state : states := START;'
)
# Add function allowing to trace current state as a string
process_level_decl
.
append
(
'function get_state return String;'
)
process_level_decl
.
append
(
'pragma export(C, get_state, "{}_state");'
.
format
(
process_name
))
# Add the declaration of the runTransition procedure
process_level_decl
.
append
(
'procedure runTransition(trId: Integer);'
)
# Generate the code of the start transition:
start_transition
=
[
'begin'
]
start_transition
.
append
(
'runTransition(0);'
)
mapping
=
{}
# Generate the code for the transitions in a mapping input-state
input_signals
=
[
sig
[
'name'
]
for
sig
in
process
.
input_signals
]
# Add timers to the mapping
input_signals
.
extend
(
process
.
timers
)
for
input_signal
in
input_signals
:
mapping
[
input_signal
]
=
{}
for
state_name
,
input_symbols
in
process
.
mapping
.
viewitems
():
if
state_name
!=
'START'
:
for
i
in
input_symbols
:
if
input_signal
.
lower
()
in
(
inp
.
lower
()
for
inp
in
i
.
inputlist
):
mapping
[
input_signal
][
state_name
]
=
i
# Generate the TASTE template
try
:
asn1_modules
=
'
\n
'
.
join
([
'with {dv};
\n
use {dv};'
.
format
(
dv
=
dv
.
replace
(
'-'
,
'_'
))
for
dv
in
process
.
asn1Modules
])
except
TypeError
:
asn1_modules
=
'-- No ASN.1 data types are used in this model'
taste_template
=
[
'''
\
-- This file was generated automatically: DO NOT MODIFY IT !
with System.IO;
use System.IO;
{dataview}
with adaasn1rtl;
use adaasn1rtl;
with Interfaces;
use Interfaces;
package body {process_name} is'''
.
format
(
process_name
=
process_name
,
dataview
=
asn1_modules
)]
# Generate the source file (.ads) header
ads_template
=
[
'''
\
-- This file was generated automatically: DO NOT MODIFY IT !
{dataview}
package {process_name} is'''
.
format
(
process_name
=
process_name
,
dataview
=
asn1_modules
)]
# Generate the the code of the procedures
inner_procedures_code
=
[]
for
proc
in
process
.
content
.
inner_procedures
:
proc_code
,
proc_local
=
generate
(
proc
)
process_level_decl
.
extend
(
proc_local
)
inner_procedures_code
.
extend
(
proc_code
)
# Generate the code for the process-level variable declarations
taste_template
.
extend
(
process_level_decl
)
# Add the code of the procedures definitions
taste_template
.
extend
(
inner_procedures_code
)
# Generate the code for each input signal (provided interface) and timers
for
signal
in
process
.
input_signals
+
[
{
'name'
:
timer
.
lower
()}
for
timer
in
process
.
timers
]:
if
signal
.
get
(
'name'
,
'START'
)
==
'START'
:
continue
pi_header
=
'procedure {sig_name}'
.
format
(
sig_name
=
signal
[
'name'
])
param_name
=
signal
.
get
(
'param_name'
)
or
'MISSING_PARAM_NAME'
# Add (optional) PI parameter (only one is possible in TASTE PI)
if
'type'
in
signal
:
typename
=
signal
[
'type'
].
ReferencedTypeName
.
replace
(
'-'
,
'_'
)
pi_header
+=
'({pName}: access asn1Scc{pType})'
.
format
(
pName
=
param_name
,
pType
=
typename
)
# Add declaration of the provided interface in the .ads file
ads_template
.
append
(
'-- Provided interface "'
+
signal
[
'name'
]
+
'"'
)
ads_template
.
append
(
pi_header
+
';'
)
pi_header
+=
' is'
taste_template
.
append
(
pi_header
)
taste_template
.
append
(
'begin'
)
taste_template
.
append
(
'case state is'
)
for
state
in
process
.
mapping
.
viewkeys
():
if
state
==
'START'
:
continue
taste_template
.
append
(
'when {state} =>'
.
format
(
state
=
state
))
input_def
=
mapping
[
signal
[
'name'
]].
get
(
state
)
if
input_def
:
for
inp
in
input_def
.
parameters
:
# Assign the (optional and unique) parameter
# to the corresponding process variable
taste_template
.
append
(
'l_{inp} := {tInp}.all;'
.
format
(
inp
=
inp
,
tInp
=
param_name
))
# Execute the correponding transition
if
input_def
.
transition
:
taste_template
.
append
(
'runTransition({idx});'
.
format
(
idx
=
input_def
.
transition_id
))
else
:
taste_template
.
append
(
'null;'
)
else
:
taste_template
.
append
(
'null;'
)
taste_template
.
append
(
'when others =>'
)
taste_template
.
append
(
'null;'
)
taste_template
.
append
(
'end case;'
)
taste_template
.
append
(
'end {sig_name};'
.
format
(
sig_name
=
signal
[
'name'
]))
taste_template
.
append
(
'
\n
'
)
# for the .ads file, generate the declaration of the required interfaces
# output signals are the asynchronous RI - only one parameter
for
signal
in
process
.
output_signals
:
ri_header
=
'procedure {sig_name}'
.
format
(
sig_name
=
signal
[
'name'
])
param_name
=
signal
.
get
(
'param_name'
)
or
'MISSING_PARAM_NAME'
# Add (optional) RI parameter
if
'type'
in
signal
:
typename
=
signal
[
'type'
].
ReferencedTypeName
.
replace
(
'-'
,
'_'
)
ri_header
+=
'({pName}: access asn1Scc{pType})'
.
format
(
pName
=
param_name
,
pType
=
typename
)
ads_template
.
append
(
'-- Required interface "'
+
signal
[
'name'
]
+
'"'
)
ads_template
.
append
(
ri_header
+
';'
)
ads_template
.
append
(
'pragma import(C, {sig}, "{proc}_RI_{sig}");'
.
format
(
sig
=
signal
[
'name'
],
proc
=
process_name
))
# for the .ads file, generate the declaration of the external procedures
for
proc
in
process
.
procedures
:
ri_header
=
'procedure {sig_name}'
.
format
(
sig_name
=
proc
.
inputString
)
params
=
[]
for
param
in
proc
.
fpar
:
typename
=
param
[
'type'
].
ReferencedTypeName
.
replace
(
'-'
,
'_'
)
params
.
append
(
'{par[name]}: access asn1Scc{partype}'
.
format
(
par
=
param
,
partype
=
typename
))
if
params
:
ri_header
+=
'('
+
';'
.
join
(
params
)
+
')'
ads_template
.
append
(
'-- Sync required interface "'
+
proc
.
inputString
)
ads_template
.
append
(
ri_header
+
';'
)
ads_template
.
append
(
'pragma import(C, {sig}, "{proc}_RI_{sig}");'
.
format
(
sig
=
proc
.
inputString
,
proc
=
process_name
))
# for the .ads file, generate the declaration of timers set/reset functions
for
timer
in
process
.
timers
:
ads_template
.
append
(
'-- Timer {} SET and RESET functions'
.
format
(
timer
))
ads_template
.
append
(
'procedure SET_{}(val: access asn1SccT_UInt32);'
.
format
(
timer
))
ads_template
.
append
(
'pragma import(C, SET_{timer}, "{proc}_RI_set_{timer}");'
.
format
(
timer
=
timer
,
proc
=
process_name
))
ads_template
.
append
(
'procedure RESET_{};'
.
format
(
timer
))
ads_template
.
append
(
'pragma import(C, RESET_{timer}, "{proc}_RI_reset_{timer}");'
.
format
(
timer
=
timer
,
proc
=
process_name
))
taste_template
.
append
(
'procedure runTransition(trId: Integer) is'
)
# Generate the code for all transitions
code_transitions
=
[]
local_decl_transitions
=
[]
# Transform inner labels of both floating labels and transitions
# into new floating labels, so that they get generated in a separate
# section of the Ada code, where they are in the scope of everybody
for
idx
in
xrange
(
len
(
process
.
content
.
floating_labels
)):
for
new_floating
in
find_labels
(
process
.
content
.
floating_labels
[
idx
].
transition
):
process
.
content
.
floating_labels
.
append
(
new_floating
)
for
proc_tr
in
process
.
transitions
:
for
new_floating
in
find_labels
(
proc_tr
):
process
.
content
.
floating_labels
.
append
(
new_floating
)
code_tr
,
tr_local_decl
=
generate
(
proc_tr
)
code_transitions
.
append
(
code_tr
)
local_decl_transitions
.
extend
(
tr_local_decl
)
# Generate code for the floating labels
code_labels
=
[]
for
label
in
process
.
content
.
floating_labels
:
code_label
,
label_decl
=
generate
(
label
)
local_decl_transitions
.
extend
(
label_decl
)
code_labels
.
extend
(
code_label
)
# Declare the local variables needed by the transitions in the template
decl
=
[
'{line}'
.
format
(
line
=
l
)
for
l
in
local_decl_transitions
]
taste_template
.
extend
(
decl
)
taste_template
.
append
(
'begin'
)
# Generate the switch-case on the transition id
taste_template
.
append
(
'case trId is'
)
for
idx
,
val
in
enumerate
(
code_transitions
):
taste_template
.
append
(
'when {idx} =>'
.
format
(
idx
=
idx
))
val
=
[
'{line}'
.
format
(
line
=
l
)
for
l
in
val
]
if
val
:
taste_template
.
extend
(
val
)
else
:
taste_template
.
append
(
'null;'
)
taste_template
.
append
(
'when others =>'
)
taste_template
.
append
(
'null;'
)
taste_template
.
append
(
'end case;'
)
# Add the code for the floating labels
taste_template
.
extend
(
code_labels
)
taste_template
.
append
(
'end runTransition;'
)
taste_template
.
append
(
'
\n
'
)
# Code of the function allowing to trace current state
taste_template
.
append
(
'function get_state return String is'
)
taste_template
.
append
(
'begin'
)
taste_template
.
append
(
"return states'Image(state);"
)
taste_template
.
append
(
'end get_state;'
)
taste_template
.
append
(
'
\n
'
)
taste_template
.
extend
(
start_transition
)
taste_template
.
append
(
'end {process_name};'
.
format
(
process_name
=
process_name
))
ads_template
.
append
(
'end {process_name};'
.
format
(
process_name
=
process_name
))
with
open
(
process_name
+
'.adb'
,
'w'
)
as
ada_file
:
ada_file
.
write
(
'
\n
'
.
join
(
format_ada_code
(
taste_template
)))
with
open
(
process_name
+
'.ads'
,
'w'
)
as
ada_file
:
ada_file
.
write
(
'
\n
'
.
join
(
format_ada_code
(
ads_template
)))
def
write_statement
(
param
,
newline
):
''' Generate the code for the special "write" operator '''
code
=
[]
string
=
''
local
=
[]
basic_type
=
find_basic_type
(
param
.
exprType
)
or
{}
type_kind
=
basic_type
.
kind
if
type_kind
.
endswith
(
'StringType'
):
if
isinstance
(
param
,
ogAST
.
PrimStringLiteral
):
# Raw string
string
=
(
'"'
+
param
.
value
[
1
:
-
1
].
replace
(
'"'
,
"'"
)
+
'"'
)
else
:
# XXX Cannot print an octet string like that...
code
,
string
,
local
=
generate
(
param
)
elif
type_kind
in
(
'IntegerType'
,
'RealType'
,
'BooleanType'
,
'Integer32Type'
):
code
,
string
,
local
=
generate
(
param
)
if
type_kind
==
'IntegerType'
:
cast
=
"Interfaces.Integer_64"
elif
type_kind
==
'RealType'
:
cast
=
'Long_Float'
elif
type_kind
==
'BooleanType'
:
cast
=
'Boolean'
elif
type_kind
==
'Integer32Type'
:
cast
=
'Integer'
string
=
"{cast}'Image({s})"
.
format
(
cast
=
cast
,
s
=
string
)
else
:
error
=
(
'Unsupported parameter in write call '
+
param
.
inputString
)
LOG
.
error
(
error
)
raise
TypeError
(
error
)
code
.
append
(
'Put{line}({string});'
.
format
(
line
=
'_Line'
if
newline
else
''
,
string
=
string
))
return
code
,
string
,
local
@
generate
.
register
(
ogAST
.
Output
)
@
generate
.
register
(
ogAST
.
ProcedureCall
)
def
_call_external_function
(
output
):
''' Generate the code of a set of output or procedure call statement '''
code
=
[]
local_decl
=
[]
# Add the traceability information
code
.
extend
(
traceability
(
output
))
for
out
in
output
.
output
:
signal_name
=
out
[
'outputName'
]
if
signal_name
.
lower
()
in
(
'write'
,
'writeln'
):
# special built-in SDL procedure for printing strings
# supports printing of native types (int, real, bool)
# but not yet complex ASN.1 structures (sequence/seqof/choice)
for
param
in
out
[
'params'
][:
-
1
]:
stmts
,
_
,
local
=
write_statement
(
param
,
newline
=
False
)
code
.
extend
(
stmts
)
local_decl
.
extend
(
local
)
for
param
in
out
[
'params'
][
-
1
:]:
# Last parameter - add newline if necessary
stmts
,
_
,
local
=
write_statement
(
param
,
newline
=
True
if
signal_name
.
lower
()
==
'writeln'
else
False
)
code
.
extend
(
stmts
)
local_decl
.
extend
(
local
)
continue
elif
signal_name
.
lower
()
==
'reset_timer'
:
# built-in operator for resetting timers. param = timer name
param
,
=
out
[
'params'
]
p_code
,
p_id
,
p_local
=
generate
(
param
)
code
.
extend
(
p_code
)
local_decl
.
extend
(
p_local
)
code
.
append
(
'RESET_{};'
.
format
(
p_id
))
continue
elif
signal_name
.
lower
()
==
'set_timer'
:
# built-in operator for setting a timer: SET(1000, timer_name)
timer_value
,
timer_id
=
out
[
'params'
]
t_code
,
t_val
,
t_local
=
generate
(
timer_value
)
p_code
,
p_id
,
p_local
=
generate
(
timer_id
)
code
.
extend
(
t_code
)
code
.
extend
(
p_code
)
local_decl
.
extend
(
t_local
)
local_decl
.
extend
(
p_local
)
# Use a temporary variable to store the timer value
tmp_id
=
'tmp'
+
str
(
out
[
'tmpVars'
][
0
])
local_decl
.
append
(
'{} : aliased asn1SccT_Uint32;'
.
format
(
tmp_id
))
code
.
append
(
'{tmp} := {val};'
.
format
(
tmp
=
tmp_id
,
val
=
t_val
))
code
.
append
(
"SET_{timer}({value}'access);"
.
format
(
timer
=
p_id
,
value
=
tmp_id
))
continue
proc
,
out_sig
=
None
,
None
try
:
out_sig
,
=
[
sig
for
sig
in
OUT_SIGNALS
if
sig
[
'name'
].
lower
()
==
signal_name
.
lower
()]
except
ValueError
:
# Not an output, try if it is an external procedure
try
:
out_sig
,
=
[
sig
for
sig
in
PROCEDURES
if
sig
.
inputString
.
lower
()
==
signal_name
.
lower
()]
except
ValueError
:
# Not external? Must be an inner procedure then.
# otherwise the parser would have barked
proc
,
=
[
sig
for
sig
in
INNER_PROCEDURES
if
sig
.
inputString
.
lower
()
==
signal_name
.
lower
()]
if
out_sig
:
list_of_params
=
[]
for
idx
,
param
in
enumerate
(
out
.
get
(
'params'
)
or
[]):
param_direction
=
'in'
try
:
# If it is an output, there is a single parameter
param_type
=
out_sig
[
'type'
]
except
TypeError
:
# Else if it is a procedure, get the type
param_type
=
out_sig
.
fpar
[
idx
][
'type'
]
param_direction
=
out_sig
.
fpar
[
idx
][
'direction'
]
typename
=
param_type
.
ReferencedTypeName
.
replace
(
'-'
,
'_'
)
p_code
,
p_id
,
p_local
=
generate
(
param
)
code
.
extend
(
p_code
)
local_decl
.
extend
(
p_local
)
# Create a temporary variable for input parameters only
if
param_direction
==
'in'
:
tmp_id
=
out
[
'tmpVars'
][
idx
]
local_decl
.
append
(
'tmp{idx} : aliased asn1Scc{oType};'
.
format
(
idx
=
tmp_id
,
oType
=
typename
))
code
.
append
(
'tmp{idx} := {p_id};'
.
format
(
idx
=
tmp_id
,
p_id
=
p_id
))
list_of_params
.
append
(
"tmp{idx}'access"
.
format
(
idx
=
out
[
'tmpVars'
][
idx
]))
else
:
# Output parameters - no need for a temp variable
list_of_params
.
append
(
"{var}'access"
.
format
(
var
=
p_id
))
if
list_of_params
:
code
.
append
(
'{RI}({params});'
.
format
(
RI
=
out
[
'outputName'
],
params
=
', '
.
join
(
list_of_params
)))
else
:
code
.
append
(
'{RI};'
.
format
(
RI
=
out
[
'outputName'
]))
else
:
# inner procedure call
list_of_params
=
[]
for
param
in
(
out
.
get
(
'params'
)
or
[]):
p_code
,
p_id
,
p_local
=
generate
(
param
)
code
.
extend
(
p_code
)
local_decl
.
extend
(
p_local
)
# no need to use temporary variables, we are in pure Ada
list_of_params
.
append
(
p_id
)
if
list_of_params
:
code
.
append
(
'{proc}({params});'
.
format
(
proc
=
proc
.
inputString
,
params
=
', '
.
join
(
list_of_params
)))
else
:
code
.
append
(
'{};'
.
format
(
proc
.
inputString
))
return
code
,
local_decl
@
generate
.
register
(
ogAST
.
TaskAssign
)
def
_task_assign
(
task
):
''' A list of assignments in a task symbol '''
code
,
local_decl
=
[],
[]
ada_string
=
''
if
task
.
comment
:
code
.
extend
(
traceability
(
task
.
comment
))
for
expr
in
task
.
elems
:
code
.
extend
(
traceability
(
expr
))
code_assign
,
ada_string
,
decl_assign
=
generate
(
expr
)
code
.
extend
(
code_assign
)
code
.
append
(
ada_string
[
1
:
-
1
]
+
';'
)
local_decl
.
extend
(
decl_assign
)
return
code
,
local_decl
@
generate
.
register
(
ogAST
.
TaskInformalText
)
def
_task_informal_text
(
task
):
''' Generate Ada comments for informal text '''
code
=
[]
if
task
.
comment
:
code
.
extend
(
traceability
(
task
.
comment
))
code
.
extend
([
'-- '
+
text
.
replace
(
'
\n
'
,
'
\n
-- '
)
for
text
in
task
.
elems
])
return
code
,
[]
@
generate
.
register
(
ogAST
.
TaskForLoop
)
def
_task_forloop
(
task
):
'''
Return the code corresponding to a for loop. Two forms are possible:
for x in range ([start], stop [, step])
for x in iterable (a SEQUENCE OF)
'''
stmt
,
local_decl
=
[],
[]
if
task
.
comment
:
stmt
.
extend
(
traceability
(
task
.
comment
))
stmt
.
extend
(
traceability
(
task
))
for
loop
in
task
.
elems
:
if
loop
[
'range'
]:
start_str
,
stop_str
=
'0'
,
''
if
loop
[
'range'
][
'start'
]:
start_stmt
,
start_str
,
start_local
=
generate
\
(
loop
[
'range'
][
'start'
])
local_decl
.
extend
(
start_local
)
stmt
.
extend
(
start_stmt
)
# ASN.1 Integers are 64 bits - we need to convert to 32 bits
if
isinstance
(
loop
[
'range'
][
'start'
],
ogAST
.
PrimInteger
):
start_str
=
'Integer({})'
.
format
(
start_str
)
if
loop
[
'range'
][
'step'
]
==
1
:
start_str
+=
'..'
stop_stmt
,
stop_str
,
stop_local
=
generate
(
loop
[
'range'
][
'stop'
])
local_decl
.
extend
(
stop_local
)
stmt
.
extend
(
stop_stmt
)
if
isinstance
(
loop
[
'range'
][
'stop'
],
ogAST
.
PrimInteger
):
stop_str
=
'Integer({})'
.
format
(
stop_str
)
if
loop
[
'range'
][
'step'
]
==
1
:
stmt
.
append
(
'for {it} in {start}{stop} loop'
.
format
(
it
=
loop
[
'var'
],
start
=
start_str
,
stop
=
stop_str
))
else
:
# Step is not directly supported in Ada, we need to use 'while'
stmt
.
extend
([
'declare'
,
'{it} : Integer := {start};'
.
format
(
it
=
loop
[
'var'
],
start
=
start_str
),
''
,
'begin'
,