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
f98201dc
Commit
f98201dc
authored
Apr 27, 2014
by
Maxime Perrotin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Minor fixes
parent
f1746aa7
Changes
26
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
1230 additions
and
1567 deletions
+1230
-1567
AdaGenerator.py
AdaGenerator.py
+239
-39
Clipboard.py
Clipboard.py
+2
-1
LlvmGenerator.py
LlvmGenerator.py
+203
-980
Renderer.py
Renderer.py
+19
-25
genericSymbols.py
genericSymbols.py
+6
-3
ogAST.py
ogAST.py
+7
-2
ogParser.py
ogParser.py
+52
-17
opengeode.py
opengeode.py
+118
-43
sdl92.g
sdl92.g
+1
-1
sdl92Lexer.py
sdl92Lexer.py
+1
-1
sdl92Parser.py
sdl92Parser.py
+125
-101
sdlSymbols.py
sdlSymbols.py
+18
-22
tests/regression/Makefile
tests/regression/Makefile
+1
-1
tests/regression/test1/Makefile
tests/regression/test1/Makefile
+1
-1
tests/regression/test10/Makefile
tests/regression/test10/Makefile
+6
-2
tests/regression/test10/challenge.pr
tests/regression/test10/challenge.pr
+144
-50
tests/regression/test10/test.c
tests/regression/test10/test.c
+9
-0
tests/regression/test2/Makefile
tests/regression/test2/Makefile
+1
-1
tests/regression/test3/Makefile
tests/regression/test3/Makefile
+1
-1
tests/regression/test3/fce.pr
tests/regression/test3/fce.pr
+270
-270
tests/regression/test4/Makefile
tests/regression/test4/Makefile
+1
-1
tests/regression/test5/Makefile
tests/regression/test5/Makefile
+1
-1
tests/regression/test6/Makefile
tests/regression/test6/Makefile
+1
-1
tests/regression/test7/Makefile
tests/regression/test7/Makefile
+1
-1
tests/regression/test8/Makefile
tests/regression/test8/Makefile
+1
-1
tests/regression/test9/Makefile
tests/regression/test9/Makefile
+1
-1
No files found.
AdaGenerator.py
View file @
f98201dc
...
...
@@ -69,6 +69,8 @@
import
logging
from
itertools
import
chain
from
singledispatch
import
singledispatch
import
ogAST
...
...
@@ -98,7 +100,6 @@ def generate(ast):
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
[:]
...
...
@@ -106,24 +107,9 @@ def _process(process):
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
''
))
# Flatten the nested states, add states to the process state list
# Requires renaming of nested states and setting chaining of transitions
def
update_terminator
(
context
,
term
,
process
):
...
...
@@ -144,9 +130,18 @@ def _process(process):
to process, updating indexes, and update terminators
'''
trans_idx
=
len
(
process
.
transitions
)
state
.
mapping
=
{
state
.
statename
+
'_'
+
key
:
state
.
mapping
.
pop
(
key
)
prefix
=
state
.
statename
+
'_'
state
.
mapping
=
{
prefix
+
key
:
state
.
mapping
.
pop
(
key
)
for
key
in
state
.
mapping
.
keys
()}
process
.
transitions
.
extend
(
state
.
transitions
)
# Add prefix to local variable names and push them at process level
for
dcl
in
state
.
variables
.
viewkeys
():
rename_everything
(
state
.
content
,
dcl
,
prefix
+
dcl
)
state
.
variables
=
{
prefix
+
key
:
state
.
variables
.
pop
(
key
)
for
key
in
state
.
variables
.
keys
()}
process
.
variables
.
update
(
state
.
variables
)
for
key
,
value
in
state
.
mapping
.
viewitems
():
# Update transition indices
if
isinstance
(
value
,
int
):
...
...
@@ -155,17 +150,60 @@ def _process(process):
for
inp
in
value
:
inp
.
transition_id
+=
trans_idx
process
.
mapping
.
update
(
state
.
mapping
)
# If composite state has entry procedures, add the call
if
state
.
entry_procedure
:
for
each
in
(
trans
for
trans
in
state
.
mapping
.
viewvalues
()
if
isinstance
(
trans
,
int
)):
call_entry
=
ogAST
.
ProcedureCall
()
call_entry
.
inputString
=
'entry'
call_entry
.
output
=
[{
'outputName'
:
prefix
+
'entry'
,
'params'
:
[],
'tmpVars'
:
[]}]
process
.
transitions
[
each
].
actions
.
insert
(
0
,
call_entry
)
# If composite state has exit procedure, add the call
if
state
.
exit_procedure
:
for
each
in
chain
(
state
.
transitions
,
(
lab
.
transition
for
lab
in
state
.
content
.
floating_labels
)):
if
each
.
terminator
.
kind
==
'return'
:
call_exit
=
ogAST
.
ProcedureCall
()
call_exit
.
inputString
=
'exit'
call_exit
.
output
=
[{
'outputName'
:
prefix
+
'exit'
,
'params'
:
[],
'tmpVars'
:
[]}]
each
.
actions
.
append
(
call_exit
)
for
inner
in
state
.
composite_states
:
inner
.
statename
=
state
.
statename
+
'_'
+
inner
.
statename
# Go recursively in inner composite states
inner
.
statename
=
prefix
+
inner
.
statename
update_composite_state
(
inner
,
process
)
for
each
in
state
.
terminators
:
# Update state names in terminators and set next transition id
# Give prefix to terminators
if
each
.
label
:
each
.
label
.
inputString
=
prefix
+
each
.
label
.
inputString
if
each
.
kind
==
'next_state'
:
each
.
inputString
=
state
.
statename
+
'_'
+
each
.
inputString
each
.
inputString
=
prefix
+
each
.
inputString
# Set next transition id
update_terminator
(
state
,
each
,
process
)
elif
each
.
kind
==
'join'
:
rename_everything
(
state
.
content
,
each
.
inputString
,
prefix
+
each
.
inputString
)
for
each
in
state
.
labels
:
# Give prefix to labels in transitions
rename_everything
(
state
.
content
,
each
.
inputString
,
prefix
+
each
.
inputString
)
# Add prefixed floating labels of the composite state to the process
process
.
content
.
floating_labels
.
extend
(
state
.
content
.
floating_labels
)
# Rename inner procedures
for
each
in
state
.
content
.
inner_procedures
:
rename_everything
(
state
.
content
,
each
.
inputString
,
prefix
+
each
.
inputString
)
each
.
inputString
=
prefix
+
each
.
inputString
process
.
content
.
inner_procedures
.
extend
(
state
.
content
.
inner_procedures
)
def
propagate_inputs
(
nested_state
,
inputlist
):
''' Nested states: Inputs at level N
bu
t be handled at level N-1
''' Nested states: Inputs at level N
mus
t be handled at level N-1
that is, all inputs of a composite states (the ones that allow
to exit the composite state from the outer scope) must be
processed by each of the substates.
...
...
@@ -190,6 +228,24 @@ def _process(process):
if
each
.
kind
==
'next_state'
:
update_terminator
(
process
,
each
,
process
)
VARIABLES
.
update
(
process
.
variables
)
INNER_PROCEDURES
.
extend
(
process
.
content
.
inner_procedures
)
# 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
(
name
for
name
in
process
.
mapping
.
iterkeys
()
...
...
@@ -437,9 +493,9 @@ package {process_name} is'''.format(process_name=process_name,
# Add the code for the floating labels
taste_template
.
extend
(
code_labels
)
if
code_labels
:
taste_template
.
append
(
'<<next_transition>>'
)
taste_template
.
append
(
'null;'
)
#
if code_labels:
taste_template
.
append
(
'<<next_transition>>'
)
taste_template
.
append
(
'null;'
)
taste_template
.
append
(
'end loop;'
)
taste_template
.
append
(
'end runTransition;'
)
taste_template
.
append
(
'
\n
'
)
...
...
@@ -587,14 +643,17 @@ def _call_external_function(output):
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
]))
# (If needed, i.e. if argument is not a local variable)
if
param_direction
==
'in'
\
and
(
not
(
isinstance
(
param
,
ogAST
.
PrimVariable
)
and
p_id
.
startswith
(
'l_'
))
or
isinstance
(
param
,
ogAST
.
PrimFPAR
)):
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
))
...
...
@@ -1228,15 +1287,14 @@ def _decision(dec):
actual_type
=
getattr
(
question_type
,
'ReferencedTypeName'
,
None
)
or
question_type
.
kind
actual_type
=
actual_type
.
replace
(
'-'
,
'_'
)
basic
=
False
if
actual_type
in
(
'IntegerType'
,
'Integer32Type'
,
'BooleanType'
,
'RealType'
,
'EnumeratedType'
,
'ChoiceEnumeratedType'
):
basic
=
True
basic
=
find_basic_type
(
question_type
).
kind
in
(
'IntegerType'
,
'Integer32Type'
,
'BooleanType'
,
'RealType'
,
'EnumeratedType'
,
'ChoiceEnumeratedType'
)
# for ASN.1 types, declare a local variable
# to hold the evaluation of the question
if
not
basic
:
local_decl
.
append
(
'tmp{idx} : aliased asn1Scc{actType};'
.
format
(
idx
=
dec
.
tmpVar
,
actType
=
actual_type
))
idx
=
dec
.
tmpVar
,
actType
=
actual_type
))
q_stmts
,
q_str
,
q_decl
=
generate
(
dec
.
question
)
# Add code-to-model traceability
code
.
extend
(
traceability
(
dec
))
...
...
@@ -1246,6 +1304,7 @@ def _decision(dec):
code
.
append
(
'tmp{idx} := {q};'
.
format
(
idx
=
dec
.
tmpVar
,
q
=
q_str
))
sep
=
'if '
for
a
in
dec
.
answers
:
code
.
extend
(
traceability
(
a
))
if
a
.
kind
in
(
'open_range'
,
'constant'
):
# Note: removed and a.transition here because empty transitions
# have a different meaning, and a "null;" statement has to be
...
...
@@ -1261,7 +1320,7 @@ def _decision(dec):
exp
=
'not '
+
exp
else
:
exp
=
'tmp{idx} {op} {ans}'
.
format
(
idx
=
dec
.
tmpVar
,
op
=
OPERANDS
[
a
.
openRangeOp
]
,
ans
=
ans_str
)
op
=
a
.
openRangeOp
.
operand
,
ans
=
ans_str
)
else
:
exp
=
'{q} {op} {ans}'
.
format
(
q
=
q_str
,
op
=
a
.
openRangeOp
.
operand
,
...
...
@@ -1334,6 +1393,7 @@ def _transition(tr):
if
tr
.
terminator
.
next_id
==
-
1
:
code
.
append
(
'state := {nextState};'
.
format
(
nextState
=
tr
.
terminator
.
inputString
))
code
.
append
(
'goto next_transition;'
)
elif
tr
.
terminator
.
kind
==
'join'
:
code
.
append
(
'goto {label};'
.
format
(
label
=
tr
.
terminator
.
inputString
))
...
...
@@ -1348,9 +1408,11 @@ def _transition(tr):
(
tr
.
terminator
.
return_expr
)
code
.
extend
(
stmts
)
local_decl
.
extend
(
local
)
code
.
append
(
'return{};'
.
format
(
' '
+
string
if
string
else
''
))
code
.
append
(
'return{};'
.
format
(
' '
+
string
if
string
else
''
))
else
:
code
.
append
(
'trId := '
+
str
(
tr
.
terminator
.
next_id
)
+
';'
)
code
.
append
(
'goto next_transition;'
)
if
empty_transition
:
# If transition does not have any statement, generate an Ada 'null;'
code
.
append
(
'null;'
)
...
...
@@ -1578,6 +1640,144 @@ def find_labels(trans):
yield
new_fl
@
singledispatch
def
rename_everything
(
ast
,
from_name
,
to_name
):
'''
Rename in all symbols all occurences of name_ref into new_name.
This is used to avoid name clashes in nested diagrams when they get
flattened. For example rename all accesses to a variable declared
in the scope of a composite state, so that they do not overwrite
a variable with the same name declared at a higher scope.
'''
pass
@
rename_everything
.
register
(
ogAST
.
Automaton
)
def
_rename_automaton
(
ast
,
from_name
,
to_name
):
''' Renaming at Automaton top level (content of digragrams) '''
transitions
=
[]
if
ast
.
start
:
rename_everything
(
ast
.
start
.
transition
,
from_name
,
to_name
)
for
each
in
ast
.
named_start
:
rename_everything
(
each
.
transition
,
from_name
,
to_name
)
for
each
in
ast
.
floating_labels
:
rename_everything
(
each
,
from_name
,
to_name
)
for
each
in
ast
.
states
:
for
inp
in
each
.
inputs
:
rename_everything
(
inp
.
transition
,
from_name
,
to_name
)
for
idx
,
param
in
enumerate
(
inp
.
parameters
):
if
param
.
lower
()
==
from_name
.
lower
():
inp
.
parameter
[
idx
]
=
to_name
if
each
.
composite
:
rename_everything
(
each
.
composite
.
content
,
from_name
,
to_name
)
for
each
in
ast
.
inner_procedures
:
# Check that from_name is not a redefined variable in the procedure
for
varname
in
each
.
variables
.
viewkeys
():
if
varname
.
lower
()
==
from_name
:
break
else
:
rename_everything
(
each
.
content
,
from_name
,
to_name
)
@
rename_everything
.
register
(
ogAST
.
Output
)
@
rename_everything
.
register
(
ogAST
.
ProcedureCall
)
def
_rename_output
(
ast
,
from_name
,
to_name
):
''' Rename actual parameter names in output/procedure calls
and possibly the procedure name '''
for
each
in
ast
.
output
:
if
each
[
'outputName'
].
lower
()
==
from_name
.
lower
():
each
[
'outputName'
]
=
to_name
for
param
in
each
[
'params'
]:
rename_everything
(
param
,
from_name
,
to_name
)
@
rename_everything
.
register
(
ogAST
.
Label
)
def
_rename_label
(
ast
,
from_name
,
to_name
):
''' Rename elements in the transition following a label '''
if
ast
.
inputString
.
lower
()
==
from_name
.
lower
():
ast
.
inputString
=
to_name
rename_everything
(
ast
.
transition
,
from_name
,
to_name
)
@
rename_everything
.
register
(
ogAST
.
Decision
)
def
_rename_decision
(
ast
,
from_name
,
to_name
):
''' Rename elements in decision '''
if
ast
.
kind
==
'question'
:
rename_everything
(
ast
.
question
)
for
each
in
ast
.
answers
:
rename_everything
(
each
,
from_name
,
to_name
)
@
rename_everything
.
register
(
ogAST
.
Answer
)
def
_rename_answer
(
ast
,
from_name
,
to_name
):
''' Rename elements in an answer branch '''
if
ast
.
kind
in
(
'constant'
,
'open_range'
):
rename_everything
(
ast
.
constant
,
from_name
,
to_name
)
elif
ast
.
kind
==
'closed_range'
:
pass
# TODO when supported
rename_everything
(
ast
.
transition
,
from_name
,
to_name
)
@
rename_everything
.
register
(
ogAST
.
Transition
)
def
_rename_transition
(
ast
,
from_name
,
to_name
):
''' Rename in all symbols of a transition '''
for
each
in
chain
(
ast
.
actions
,
ast
.
terminators
):
# Label, output, task, decision, terminators
rename_everything
(
each
,
from_name
,
to_name
)
@
rename_everything
.
register
(
ogAST
.
Terminator
)
def
_rename_terminator
(
ast
,
from_name
,
to_name
):
''' Rename terminators: join/labels, next_state '''
if
ast
.
inputString
.
lower
()
==
from_name
.
lower
():
ast
.
inputString
=
to_name
rename_everything
(
ast
.
label
,
from_name
,
to_name
)
rename_everything
(
ast
.
return_expr
,
from_name
,
to_name
)
@
rename_everything
.
register
(
ogAST
.
TaskAssign
)
def
_rename_task_assign
(
ast
,
from_name
,
to_name
):
''' List of assignments '''
for
each
in
ast
.
elems
:
rename_everything
(
each
,
from_name
,
to_name
)
@
rename_everything
.
register
(
ogAST
.
TaskForLoop
)
def
_rename_forloop
(
ast
,
from_name
,
to_name
):
''' List of FOR loops '''
for
each
in
ast
.
elems
:
rename_everything
(
each
[
'list'
],
from_name
,
to_name
)
rename_everything
(
each
[
'range'
][
'start'
],
from_name
,
to_name
)
rename_everything
(
each
[
'range'
][
'stop'
],
from_name
,
to_name
)
rename_everything
(
each
[
'transition'
],
from_name
,
to_name
)
@
rename_everything
.
register
(
ogAST
.
ExprPlus
)
@
rename_everything
.
register
(
ogAST
.
ExprMul
)
@
rename_everything
.
register
(
ogAST
.
ExprMinus
)
@
rename_everything
.
register
(
ogAST
.
ExprEq
)
@
rename_everything
.
register
(
ogAST
.
ExprNeq
)
@
rename_everything
.
register
(
ogAST
.
ExprGt
)
@
rename_everything
.
register
(
ogAST
.
ExprGe
)
@
rename_everything
.
register
(
ogAST
.
ExprLt
)
@
rename_everything
.
register
(
ogAST
.
ExprLe
)
@
rename_everything
.
register
(
ogAST
.
ExprDiv
)
@
rename_everything
.
register
(
ogAST
.
ExprMod
)
@
rename_everything
.
register
(
ogAST
.
ExprRem
)
@
rename_everything
.
register
(
ogAST
.
ExprAssign
)
@
rename_everything
.
register
(
ogAST
.
ExprOr
)
@
rename_everything
.
register
(
ogAST
.
ExprIn
)
@
rename_everything
.
register
(
ogAST
.
ExprAnd
)
@
rename_everything
.
register
(
ogAST
.
ExprXor
)
@
rename_everything
.
register
(
ogAST
.
ExprAppend
)
@
rename_everything
.
register
(
ogAST
.
ExprAssign
)
def
_rename_expr
(
ast
,
from_name
,
to_name
):
''' Two-sided expressions '''
rename_everything
(
ast
.
left
,
from_name
,
to_name
)
rename_everything
(
ast
.
right
,
from_name
,
to_name
)
@
rename_everything
.
register
(
ogAST
.
PrimPath
)
@
rename_everything
.
register
(
ogAST
.
PrimVariable
)
def
_rename_path
(
ast
,
from_name
,
to_name
):
''' Ultimate seek point for the renaming: primary path/variables '''
if
ast
.
value
[
0
].
lower
()
==
from_name
.
lower
():
ast
.
value
[
0
]
=
to_name
def
format_ada_code
(
stmts
):
''' Indent properly the Ada code '''
indent
=
0
...
...
Clipboard.py
View file @
f98201dc
...
...
@@ -90,7 +90,8 @@ def copy_branch(top_level_item):
(
term
.
pos_x
,
term
.
pos_y
,
term
.
width
,
term
.
height
).
center
())
for
symbol
in
symbols
:
if
(
isinstance
(
symbol
,
sdlSymbols
.
State
)
and
[
c
for
c
in
symbol
.
childSymbols
()
if
isinstance
(
c
,
sdlSymbols
.
Input
)]):
symbol
.
childSymbols
()
if
isinstance
(
c
,
(
sdlSymbols
.
Input
,
sdlSymbols
.
Connect
))]):
term_branch
,
term_inators
=
copy_branch
(
symbol
)
branch
.
extend
(
term_branch
)
res_terminators
.
extend
(
term_inators
)
...
...
LlvmGenerator.py
View file @
f98201dc
This diff is collapsed.
Click to expand it.
Renderer.py
View file @
f98201dc
...
...
@@ -101,18 +101,19 @@ def _automaton(ast, scene):
top_level_symbols
.
append
(
render
(
label
,
scene
,
ast
.
states
))
# Render floating states
nested_states
=
{}
nested_states
=
[]
for
state
in
ast
.
states
:
# Create only floating states
try
:
new_state
=
render
(
state
,
scene
=
scene
,
states
=
ast
.
states
,
terminators
=
ast
.
parent
.
terminators
)
if
new_state
.
nested_scene
:
if
str
(
new_state
).
lower
()
in
nested_states
.
viewkeys
():
if
str
(
new_state
).
lower
()
in
nested_states
:
#
.viewkeys():
new_state
.
nested_scene
=
None
else
:
nested_states
[
str
(
new_state
).
lower
()]
=
\
new_state
.
nested_scene
nested_states
.
append
(
str
(
new_state
).
lower
())
#nested_states[str(new_state).lower()] = \
# new_state.nested_scene
except
TypeError
:
# Discard terminators (see _state function for explanation)
pass
...
...
@@ -171,8 +172,7 @@ def _start(ast, scene, states, parent=None):
start_symbol
=
sdlSymbols
.
Start
(
ast
)
scene
.
addItem
(
start_symbol
)
if
ast
.
transition
:
render
(
ast
.
transition
,
scene
=
scene
,
parent
=
start_symbol
,
states
=
states
)
render
(
ast
.
transition
,
scene
=
scene
,
parent
=
start_symbol
,
states
=
states
)
return
start_symbol
...
...
@@ -195,8 +195,7 @@ def _procedure_start(ast, scene, states, parent=None):
start_symbol
=
sdlSymbols
.
ProcedureStart
(
ast
)
scene
.
addItem
(
start_symbol
)
if
ast
.
transition
:
render
(
ast
.
transition
,
scene
=
scene
,
parent
=
start_symbol
,
states
=
states
)
render
(
ast
.
transition
,
scene
=
scene
,
parent
=
start_symbol
,
states
=
states
)
return
start_symbol
...
...
@@ -209,24 +208,19 @@ def _floating_label(ast, scene, states, parent=None):
scene
.
addItem
(
lab
)
lab
.
setPos
(
ast
.
pos_x
,
ast
.
pos_y
)
if
ast
.
transition
:
render
(
ast
.
transition
,
scene
=
scene
,
parent
=
lab
,
states
=
states
)
render
(
ast
.
transition
,
scene
=
scene
,
parent
=
lab
,
states
=
states
)
return
lab
@
render
.
register
(
ogAST
.
Transition
)
def
_transition
(
ast
,
scene
,
parent
,
states
):
''' Add a transition to a scene '''
for
action_symbol
in
ast
.
actions
:
for
each
in
ast
.
actions
:
# pylint: disable=E1111
parent
=
render
(
action_symbol
,
scene
=
scene
,
parent
=
parent
,
states
=
states
)
parent
=
render
(
each
,
scene
=
scene
,
parent
=
parent
,
states
=
states
)
if
ast
.
terminator
:
render
(
ast
.
terminator
,
scene
=
scene
,
parent
=
parent
,
states
=
states
)
render
(
ast
.
terminator
,
scene
=
scene
,
parent
=
parent
,
states
=
states
)
@
render
.
register
(
ogAST
.
Comment
)
...
...
@@ -296,8 +290,7 @@ def _terminator(ast, scene, parent, states):
''' Create a TERMINATOR symbol '''
if
ast
.
label
:
# pylint: disable=E1111
parent
=
render
(
ast
.
label
,
scene
=
scene
,
parent
=
parent
,
states
=
states
)
parent
=
render
(
ast
.
label
,
scene
=
scene
,
parent
=
parent
,
states
=
states
)
if
ast
.
kind
==
'next_state'
:
LOG
.
debug
(
'ADDING NEXT_STATE '
+
ast
.
inputString
)
# Create a new state symbol
...
...
@@ -309,9 +302,11 @@ def _terminator(ast, scene, parent, states):
state_ast
.
pos_x
==
ast
.
pos_x
and
state_ast
.
pos_y
==
ast
.
pos_y
):
LOG
.
debug
(
'MERGING TERMINATOR "'
+
ast
.
inputString
+
'"'
)
for
input_ast
in
state_ast
.
inputs
:
render
(
input_ast
,
scene
=
scene
,
parent
=
symbol
,
states
=
states
)
symbol
.
nested_scene
=
state_ast
.
composite
or
\
ogAST
.
CompositeState
()
for
each
in
chain
(
state_ast
.
inputs
,
state_ast
.
connects
):
render
(
each
,
scene
=
scene
,
parent
=
symbol
,
states
=
states
)
break
elif
ast
.
kind
==
'join'
:
symbol
=
sdlSymbols
.
Join
(
parent
,
ast
)
elif
ast
.
kind
in
(
'return'
,
'stop'
):
...
...
@@ -338,12 +333,11 @@ def _input(ast, scene, parent, states):
return
inp
@
render
.
register
(
ogAST
.
Connect
)
def
_
inpu
t
(
ast
,
scene
,
parent
,
states
):
def
_
connec
t
(
ast
,
scene
,
parent
,
states
):
''' Add connect symbol from the AST to the scene '''
# Note: PROVIDED clause is not supported
conn
=
sdlSymbols
.
Connect
(
parent
,
ast
=
ast
)
if
conn
not
in
scene
.
items
():
scene
.
addItem
(
inp
)
scene
.
addItem
(
conn
)
if
not
parent
:
conn
.
setPos
(
ast
.
pos_x
,
ast
.
pos_y
)
if
ast
.
transition
:
...
...
genericSymbols.py
View file @
f98201dc
...
...
@@ -375,7 +375,7 @@ class EditableText(QGraphicsTextItem, object):
text_cursor
.
clearSelection
()
self
.
setTextCursor
(
text_cursor
)
# If something has changed, check syntax and create undo command
if
(
self
.
oldSize
!=
self
.
parentItem
().
boundingRect
()
or
if
(
self
.
oldSize
!=
self
.
parentItem
().
boundingRect
()
or
self
.
oldText
!=
str
(
self
)):
# Call syntax checker from item containing the text (if any)
self
.
parentItem
().
check_syntax
()
...
...
@@ -624,8 +624,7 @@ class Symbol(QObject, QGraphicsPathItem, object):
def
is_composite
(
self
):
''' Return True if nested scene has something in it '''
try
:
return
self
.
allow_nesting
and
any
(
item
.
isVisible
()
for
item
in
self
.
_nested_scene
.
items
())
return
any
(
self
.
_nested_scene
.
visible_symb
)
except
AttributeError
:
return
False
...
...
@@ -979,6 +978,10 @@ class Symbol(QObject, QGraphicsPathItem, object):
else
:
self
.
mode
=
'Move'
def
double_click
(
self
):
''' Handle double click on symbol - redefined at symbol level '''
pass
def
mouse_move
(
self
,
event
):
''' Handle resizing of items - moving is handled in subclass '''
self
.
updateConnectionPoints
()
...
...
ogAST.py
View file @
f98201dc
...
...
@@ -173,6 +173,7 @@ class PrimPath(Primary):
is_raw
=
False
class
PrimVariable
(
PrimPath
):
pass
# XXX should not be raw for codegen
class
PrimFPAR
(
PrimVariable
):
pass
class
PrimEnumeratedValue
(
Primary
):
pass
class
PrimInteger
(
Primary
):
pass
class
PrimReal
(
Primary
):
pass
...
...
@@ -770,8 +771,12 @@ class CompositeState(Process):
self
.
exit_procedure
=
None
# Body can contain text areas, procedures, composite states,
# one nameless START, named START (one per entrypoint), states,
# and floating labels.
# XXX check what to do with local DCL and timers
# amd floating labels
def
__repr__
(
self
):
''' Debug output for composite state '''
return
'COMPOSITE STATE {exp} ({l},{c})'
.
format
(
exp
=
self
.
statename
,
l
=
self
.
line
,
c
=
self
.
charPositionInLine
)
class
Block
(
object
):
...
...
ogParser.py
View file @
f98201dc
...
...
@@ -320,6 +320,27 @@ def fix_special_operators(op_name, expr_list, context):
and
not
basic
.
kind
.
endswith
(
'StringType'
):
# Currently supported printable types
raise
TypeError
(
'Write operator does not support type'
)
elif
op_name
.
lower
()
==
'set_timer'
:
if
len
(
expr_list
)
!=
2
:
raise
TypeError
(
'SET_TIMER has 2 parameters: (int, timer_name)'
)
basic
=
find_basic_type
(
expr_list
[
0
].
exprType
)
if
not
basic
.
kind
.
startswith
(
'Integer'
):
raise
TypeError
(
'SET_TIMER first parameter is not an integer'
)
timer
=
expr_list
[
1
].
inputString
for
each
in
context
.
timers
:
if
each
.
lower
()
==
timer
.
lower
():
break
else
:
raise
TypeError
(
'Timer {} is not defined'
.
format
(
timer
))
elif
op_name
.
lower
==
'reset_timer'
:
if
len
(
expr_list
)
!=
1
:
raise
TypeError
(
'RESET_TIMER has 1 parameter: timer_name'
)
timer
=
expr_list
[
0
].
inputString
for
each
in
context
.
timers
:
if
each
.
lower
()
==
timer
.
lower
():
break
else
:
raise
TypeError
(
'Timer {} is not defined'
.
format
(
timer
))
else
:
# TODO: other operators
return
...
...
@@ -603,8 +624,8 @@ def find_variable(var, context):
result
=
UNKNOWN_TYPE
LOG
.
debug
(
'[find_variable] checking if '
+
str
(
var
)
+
' is defined'
)
# all DCL-variables
all_visible_variables
=
dict
(
context
.
variables
)
all_visible_variables
.
update
(
context
.
global_
variables
)
all_visible_variables
=
dict
(
context
.
global_
variables
)
all_visible_variables
.
update
(
context
.
variables
)
# First check locally, i.e. in FPAR
try
:
for
variable
in
context
.
fpar
:
...
...
@@ -746,7 +767,14 @@ def fix_expression_types(expr, context):
try
:
#exprType = find_variable(uk_expr.inputString, context)
exprType
=
find_variable
(
uk_expr
.
value
[
0
],
context
)
setattr
(
expr
,
side
,
ogAST
.
PrimVariable
(
primary
=
uk_expr
))
# Differentiate DCL and FPAR variables
use_type
=
ogAST
.
PrimVariable
if
isinstance
(
context
,
ogAST
.
Procedure
):
for
each
in
context
.
fpar
:
if
each
[
'name'
].
lower
()
==
uk_expr
.
value
[
0
].
lower
():
use_type
=
ogAST
.
PrimFPAR
break
setattr
(
expr
,
side
,
use_type
(
primary
=
uk_expr
))
getattr
(
expr
,
side
).
exprType
=
exprType
except
AttributeError
:
pass
...
...
@@ -1349,7 +1377,7 @@ def composite_state(root, parent=None, context=None):
warnings
.
extend
(
warn
)
comp
.
content
.
textAreas
.
append
(
textarea
)
elif
child
.
type
==
lexer
.
PROCEDURE
:
new_proc
,
err
,
warn
=
procedure
(
child
,
context
=
proc
)
new_proc
,
err
,
warn
=
procedure
(
child
,
context
=
comp
)
errors
.
extend
(
err
)
warnings
.
extend
(
warn
)
if
new_proc
.
inputString
.
strip
().
lower
()
==
'entry'
:
...
...
@@ -1363,8 +1391,7 @@ def composite_state(root, parent=None, context=None):