#include "WfAnalyzer.h"
namespace
{
namespace
{
namespace
{
using
namespace
collections
;
using
namespace
reflection
;
using
namespace
reflection
::
description
;
<
>
GenerateCoroutineInvalidId
()
{
auto
=
<
>();
refOne
.
=
L"1"
;
auto
=
<
>();
refInvalid
=
::
;
refInvalid
refOne
;
return
refInvalid
;
}
class
FindCoroutineAwaredStatementVisitor
:
public
empty_visitor
::
{
public
:
<
*>&
;
bool
=
false
;
FindCoroutineAwaredStatementVisitor
(
<
*>&
)
:awaredStatements(
)
{
}
bool
(
<
>
)
{
if
(!
)
return
false
;
=
false
;
(
this
);
if
(
)
{
.
(
.
());
}
return
;
}
void
(
*
)
override
{
=
(
->
);
}
void
(
*
)
override
{
=
true
;
}
void
(
*
)
override
{
CHECK_FAIL(L"FindCoroutineAwaredStatementVisitor::Visit(WfStateMachineStatement*)#Internal error, state machine statement is not allowed in $coroutine expression.");
do
{
throw
(
L"FindCoroutineAwaredStatementVisitor::Visit(WfStateMachineStatement*)#Internal error, state machine statement is not allowed in $coroutine expression."
);}
while
(
0
);
}
void
(
*
)
override
{
=
true
;
}
void
(
*
)
override
{
=
true
;
}
void
(
*
)
override
{
=
true
;
}
void
(
*
)
override
{
bool
=
(
->
);
bool
=
(
->
);
=
a
||
b
;
}
void
(
*
)
override
{
=
(
->
);
}
void
(
*
)
override
{
bool
=
(
->
);
bool
=
(
->
);
bool
=
(
->
);
=
a
||
b
||
c
;
}
void
(
*
)
override
{
bool
=
false
;
FOREACH(Ptr<WfStatement>, stat, node->statements)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
stat
);)
{
bool
=
(
stat
);
result
|=
a
;
}
=
result
;
}
void
(
*
)
override
{
=
true
;
}
};
void
FindCoroutineAwaredStatements
(
<
>
,
<
*>&
)
{
FindCoroutineAwaredStatementVisitor
(
).
(
);
}
class
FindCoroutineAwaredVariableVisitor
:
public
empty_visitor
::
{
public
:
<
*>&
;
FindCoroutineAwaredVariableVisitor
(
<
*>&
)
:awaredVariables(
)
{
}
void
(
*
)
override
{
->
(
this
);
}
void
(
*
)
override
{
}
void
(
*
)
override
{
CHECK_FAIL(L"FindCoroutineAwaredVariableVisitor::Visit(WfStateMachineStatement*)#Internal error, state machine statement is not allowed in $coroutine expression.");
do
{
throw
(
L"FindCoroutineAwaredVariableVisitor::Visit(WfStateMachineStatement*)#Internal error, state machine statement is not allowed in $coroutine expression."
);}
while
(
0
);
}
void
(
*
)
override
{
.
(
);
}
};
class
FindCoroutineAwaredBlockVisitor
:
public
empty_visitor
::
{
public
:
<
*>&
;
FindCoroutineAwaredBlockVisitor
(
<
*>&
)
:awaredVariables(
)
{
}
void
(
*
)
override
{
}
void
(
*
)
override
{
}
void
(
*
)
override
{
CHECK_FAIL(L"FindCoroutineAwaredBlockVisitor::Visit(WfStateMachineStatement*)#Internal error, state machine statement is not allowed in $coroutine expression.");
do
{
throw
(
L"FindCoroutineAwaredBlockVisitor::Visit(WfStateMachineStatement*)#Internal error, state machine statement is not allowed in $coroutine expression."
);}
while
(
0
);
}
void
(
*
)
override
{
FindCoroutineAwaredVariableVisitor
(
);
FOREACH(Ptr<WfStatement>, stat, node->statements)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
stat
);)
{
stat
(&
visitor
);
}
}
};
void
FindCoroutineAwaredVariables
(
*
,
<
*>&
)
{
FindCoroutineAwaredBlockVisitor
(
);
->
(&
visitor
);
}
void
FindCoroutineReferenceRenaming
(
*
,
<
*>&
,
<
*>&
,
<
*,
>&
)
{
=
0
;
auto
= [&](
const
&
)
{
if
(
name
.
() >
0
&&
name
0
] ==
L'<'
)
{
vint index = INVLOC.FindFirst(name, L">", Locale::None).key;
=
vl
::
::
().
(
name
,
L">"
,
::
).key;
auto
=
name
.
(
1
,
index
-
1
);
auto
=
name
.
(
index
+
1
,
name
.
() -
index
-
1
);
return
L"<co"
+
(
renameCounter
++) +
L"-"
+
category
+
L">"
+
local
;
}
else
{
return
L"<co"
+
(
renameCounter
++) +
L">"
+
name
;
}
};
FOREACH(WfVariableStatement*, stat, awaredVariables)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
*>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
*
;
__foreach_iterator__
.
(
stat
);)
{
auto
=
->
stat
];
auto
=
scope
stat
->
.
]
0
];
auto
=
rename
(
stat
->
.
);
.
(
symbol
.
(),
name
);
}
FOREACH(WfStatement*, stat, awaredStatements)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
*>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
*
;
__foreach_iterator__
.
(
stat
);)
{
if
(
auto
=
dynamic_cast
<
*>(
stat
))
{
if
(
tryStat
->
)
{
auto
=
->
tryStat
->
.
()]
.
();
auto
=
scope
->
tryStat
->
.
]
0
];
auto
=
rename
(
tryStat
->
.
);
.
(
symbol
.
(),
name
);
}
}
else
if
(
auto
=
dynamic_cast
<
*>(
stat
))
{
if
(
ifStat
->
.
!=
L""
)
{
auto
=
->
ifStat
->
.
()]
.
();
auto
=
scope
->
ifStat
->
.
]
0
];
auto
=
rename
(
ifStat
->
.
);
.
(
symbol
.
(),
name
);
}
}
}
}
class
;
class
:
public
{
public
:
<
>
;
*
=
nullptr
;
};
enum
class
{
,
,
};
class
:
public
{
public
:
=
::
;
bool
=
false
;
<
<
>>
;
<
<
>>
;
*
=
nullptr
;
*
=
nullptr
;
*
=
nullptr
;
*
=
nullptr
;
};
class
:
public
{
typedef
<
*,
<
>>
;
public
:
<
<
>>
;
*
=
nullptr
;
*
=
nullptr
;
;
*
(
*
)
{
auto
=
<
>();
node
=
;
.
(
node
);
return
node
.
();
}
*
(
*
,
*
,
=
::
)
{
auto
=
(
);
node
->
=
;
if
(
)
{
CHECK_ERROR(head->destination == nullptr, L"FlowChart::AppendNode(FlowChartNode*, FlowChartNode*, FlowChartNodeAction)#Cannot append a new node to a flow chart node that already has a default destination.");
do
{
if
(!(
->
==
nullptr
))
throw
(
L"FlowChart::AppendNode(FlowChartNode*, FlowChartNode*, FlowChartNodeAction)#Cannot append a new node to a flow chart node that already has a default destination."
);}
while
(
0
);
->
=
node
;
}
return
node
;
}
*
(
*
,
*
)
{
if
(
==
nullptr
)
{
return
(
);
}
else
if
(
->
.
() >
0
||
->
!=
)
{
CHECK_ERROR(head->destination == nullptr, L"FlowChart::EnsureAppendStatement(FlowChartNode*, FlowChartNode*)#Cannot append a statement to a flow chart node that already has a default destination.");
do
{
if
(!(
->
==
nullptr
))
throw
(
L"FlowChart::EnsureAppendStatement(FlowChartNode*, FlowChartNode*)#Cannot append a statement to a flow chart node that already has a default destination."
);}
while
(
0
);
auto
=
(
);
->
=
node
;
return
node
;
}
else
{
return
;
}
}
};
class
GenerateFlowChartModuleVisitor
:
public
CopyWithExpandVirtualVisitor
{
public
:
*
;
<
*,
>&
;
GenerateFlowChartModuleVisitor
(
*
,
<
*,
>&
)
:
CopyWithExpandVirtualVisitor
(
true
)
, manager(
)
, referenceRenaming(
)
{
}
void
(
*
)
override
{
copy_visitor
::
::
(
);
=
->
.
().
(
);
if
(
index
!= -
1
)
{
auto
=
->
.
()
index
];
=
.
().
(
resolvingResult
.
.
());
if
(
index
!= -
1
)
{
.
<
>()
.
.
()
index
];
}
}
}
};
class
GenerateFlowChartStatementVisitor
:
public
,
public
::
,
public
::
{
public
:
enum
class
{
,
,
,
,
};
struct
{
*
=
nullptr
;
=
::
;
;
*
=
nullptr
;
*
=
nullptr
;
*
=
nullptr
;
<
>
;
};
public
:
*
;
<
*>&
;
<
*,
>&
;
<
>
;
*
;
*
;
*
;
*
=
nullptr
;
*
=
nullptr
;
GenerateFlowChartStatementVisitor
(
*
,
<
*>&
,
<
*,
>&
,
<
>
,
*
,
*
,
*
)
:manager(
)
, awaredStatements(
)
, referenceRenaming(
)
, flowChart(
)
, headNode(
)
, catchNode(
)
, scopeContext(
)
{
}
#define COPY_AST(STATEMENT) GenerateFlowChartModuleVisitor(manager, referenceRenaming).CreateField(STATEMENT)
void
(
*
,
*
,
<
>
)
{
if
(!
)
{
=
(
,
);
=
;
}
=
(
,
,
,
).
;
}
void
AppendUnawaredCopiedStatement
(
*
,
*
,
<
>
)
{
if
(!
)
{
=
(
,
);
=
;
}
->
.
(
);
}
*
(
,
bool
,
const
=
::
)
{
auto
=
;
while
(
current
)
{
bool
=
false
;
if
(
current
->
==
)
{
if
(
L""
||
current
->
==
)
{
found
=
true
;
}
}
if
(
&&
found
)
break
;
if
(
current
->
)
{
(
,
current
->
,
current
->
);
}
if
(!
&&
found
)
break
;
current
=
current
->
;
}
return
current
;
}
static
<
*,
*>
(
*
,
<
*>&
,
<
*,
>&
,
<
>
,
*
,
*
,
*
,
<
>
)
{
GenerateFlowChartStatementVisitor
(
,
,
,
,
,
,
);
if
(
.
(
.
()))
{
(&
visitor
);
}
else
{
visitor.AppendUnawaredCopiedStatement(catchNode, scopeContext, COPY_AST(statement));
visitor
.
AppendUnawaredCopiedStatement
(
,
,
GenerateFlowChartModuleVisitor
(
,
).
(
));
}
return
{
visitor
.
,
visitor
.
};
}
<
*,
*>
(
*
,
*
,
*
,
<
>
)
{
return
(
,
,
,
,
,
,
,
);
}
void
(
*
)
override
{
auto
=
(
::
,
false
);
=
(
,
);
=
;
auto
=
<
>();
branch
=
targetContext
->
;
->
.
(
branch
);
}
void
(
*
)
override
{
auto
=
(
::
,
true
);
=
(
,
);
=
;
auto
=
<
>();
branch
=
targetContext
->
;
->
.
(
branch
);
}
void
(
*
)
override
{
auto
=
(
::
,
false
);
AppendUnawaredCopiedStatement(catchNode, scopeContext, COPY_AST(node));
AppendUnawaredCopiedStatement
(
,
,
GenerateFlowChartModuleVisitor
(
,
).
(
));
auto
=
<
>();
branch
=
targetContext
->
;
->
.
(
branch
);
}
void
(
*
)
override
{
AppendUnawaredCopiedStatement(catchNode, scopeContext, COPY_AST(node));
AppendUnawaredCopiedStatement
(
,
,
GenerateFlowChartModuleVisitor
(
,
).
(
));
}
void
(
WfRaiseExceptionStatement
*
)
override
{
AppendUnawaredCopiedStatement(catchNode, scopeContext, COPY_AST(node));
AppendUnawaredCopiedStatement
(
,
,
GenerateFlowChartModuleVisitor
(
,
).
(
));
}
void
(
*
)
{
=
(
,
);
{
auto
=
<
>();
->
.
(
branch
);
auto
=
->
];
auto
=
scope
->
.
]
0
].
();
{
auto
=
<
>();
refExpr
.
symbol
];
auto
=
<
>();
assignExpr
=
::
;
assignExpr
refExpr
;
assignExpr->second = COPY_AST(node->expression);
assignExpr
GenerateFlowChartModuleVisitor
(
,
).
(
->
);
auto
=
<
>();
stat
assignExpr
;
((
<
>)
stat
,
->
);
->
.
(
stat
);
}
{
auto
=
<
>();
refExpr
.
symbol
];
auto
=
<
>();
testExpr
=
::
;
testExpr
refExpr
;
((
<
>)
testExpr
,
->
);
branch
testExpr
;
}
}
=
(
);
{
auto
=
(
nullptr
,
,
,
->
);
pair
.
->
=
;
->
0
]
=
pair
.
;
}
if
(
->
)
{
auto
=
(
nullptr
,
,
,
->
);
pair
.
->
=
;
->
=
pair
.
;
}
else
{
->
=
;
}
}
void
(
*
)
{
=
(
,
);
=
(
);
while
(
true
)
{
auto
=
<
>();
->
.
(
branch
);
branch->condition = COPY_AST(node->expression);
branch
GenerateFlowChartModuleVisitor
(
,
).
(
->
);
auto
=
(
nullptr
,
,
,
->
);
pair
.
->
=
;
branch
=
pair
.
;
auto
=
dynamic_cast
<
*>(
->
.
());
if
(
next
&&
next
->
.
==
L""
)
{
=
next
;
}
else
{
break
;
}
}
if
(
->
)
{
auto
=
(
nullptr
,
,
,
->
);
pair
.
->
=
;
->
=
pair
.
;
}
else
{
->
=
;
}
}
void
(
*
)
override
{
if
(
->
.
==
L""
)
{
(
);
}
else
{
(
);
}
}
void
(
*
)
override
{
=
(
,
);
{
auto
=
<
>();
->
.
(
branch
);
branch->condition = COPY_AST(node->condition);
branch
GenerateFlowChartModuleVisitor
(
,
).
(
->
);
}
auto
=
(
);
{
auto
=
<
>();
loopEnd
->
.
(
branch
);
branch->condition = COPY_AST(node->condition);
branch
GenerateFlowChartModuleVisitor
(
,
).
(
->
);
}
=
(
);
;
loopContext
.
=
;
loopContext
.
=
::
;
loopContext
.
=
loopEnd
;
loopContext
.
=
;
auto
=
(
nullptr
,
, &
loopContext
,
->
);
pair
.
->
=
loopEnd
;
->
0
]
=
pair
.
;
loopEnd
->
0
]
=
pair
.
;
->
=
;
loopEnd
->
=
;
}
*
GetExceptionVariableSymbol
(
*
)
{
if
(
->
)
{
auto
=
->
->
.
()]
.
();
auto
=
scope
->
->
.
]
0
];
return
symbol
.
();
}
else
{
=
.
().
(
);
if
(
index
== -
1
)
{
auto
=
<
>(
nullptr
);
symbol
=
L"ex"
;
symbol
<
<
>>::
();
.
(
,
symbol
);
.
(
symbol
.
(),
L"<co-tempexvar"
+
(
.
() -
1
) +
L">ex"
);
return
symbol
.
();
}
return
.
()
index
].
();
}
}
<
*,
*>
(
*
,
*
)
{
auto
=
(
nullptr
,
,
,
->
);
pair
.
->
=
GetExceptionVariableSymbol
(
);
return
pair
;
}
<
*,
*>
(
*
,
*
)
{
return
(
nullptr
,
,
,
->
);
}
<
*,
*>
(
*
,
*
)
{
auto
=
(
nullptr
,
,
,
->
);
auto
=
(
);
{
pair
.
->
=
GetExceptionVariableSymbol
(
);
auto
=
<
>();
refExpr
.
pair
.
->
];
auto
=
<
>();
memberExpr
refExpr
;
memberExpr
.
=
L"Message"
;
auto
=
<
WfRaiseExceptionStatement
>();
raiseStat
memberExpr
;
((
<
>)
raiseStat
,
->
);
raiseNode
->
.
(
raiseStat
);
}
pair
.
->
=
raiseNode
;
return
{
pair
.
,
raiseNode
};
}
void
(
*
)
override
{
;
tryContext
.
=
;
tryContext
.
=
::
;
if
(
->
)
{
tryContext
.
=
;
tryContext
.
->
;
}
if
(
->
&& !
->
)
{
auto
=
(
,
);
(
pairCatch
.
, &
tryContext
,
->
);
auto
=
(
);
pairCatch
.
->
=
endNode
;
->
=
endNode
;
=
endNode
;
}
else
if
(!
->
&&
->
)
{
auto
=
(
,
);
(
pairFinallyAndRaise
.
, &
tryContext
,
->
);
auto
=
(
,
);
auto
=
(
);
->
=
pairFinally
.
;
pairFinally
.
->
=
endNode
;
pairFinallyAndRaise
.
->
=
endNode
;
=
endNode
;
}
else
{
auto
=
(
,
);
auto
=
(
,
pairFinallyAndRaise
.
);
(
pairCatch
.
, &
tryContext
,
->
);
auto
=
(
,
);
auto
=
(
);
->
=
pairFinally
.
;
pairCatch
.
->
=
pairFinally
.
;
pairFinally
.
->
=
endNode
;
pairFinallyAndRaise
.
->
=
endNode
;
=
endNode
;
}
}
void
(
*
)
override
{
if
(
->
.
==
L""
)
{
=
(
,
);
=
;
FOREACH_INDEXER(Ptr<WfStatement>, stat, index, node->statements)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
if
(
bool
=
true
)
for
(
=
0
;
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
stat
);
index
++)
{
auto
=
(
,
,
,
stat
);
=
pair
.
;
}
}
else
{
=
(
,
);
auto
=
(
);
=
;
;
blockContext
.
=
;
blockContext
.
=
::
;
blockContext
.
->
.
;
blockContext
.
=
;
blockContext
.
=
blockEnd
;
FOREACH_INDEXER(Ptr<WfStatement>, stat, index, node->statements)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
if
(
bool
=
true
)
for
(
=
0
;
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
stat
);
index
++)
{
auto
=
(
,
, &
blockContext
,
stat
);
=
pair
.
;
}
->
=
blockEnd
;
=
blockEnd
;
}
}
void
(
*
)
override
{
auto
=
(
::
,
false
,
->
.
);
=
(
,
);
=
;
auto
=
<
>();
branch
=
targetContext
->
;
->
.
(
branch
);
}
void
(
*
)
override
{
=
(
,
);
=
;
auto
=
->
];
auto
=
scope
->
.
]
0
].
();
auto
=
<
>();
refExpr
.
symbol
];
auto
=
<
>();
assignExpr
=
::
;
assignExpr
refExpr
;
assignExpr->second = COPY_AST(node->variable->expression);
assignExpr
GenerateFlowChartModuleVisitor
(
,
).
(
->
);
auto
=
<
>();
stat
assignExpr
;
((
<
>)
stat
,
->
);
AppendUnawaredCopiedStatement
(
,
,
stat
);
}
void
(
*
)
override
{
AppendUnawaredCopiedStatement(catchNode, scopeContext, COPY_AST(node));
AppendUnawaredCopiedStatement
(
,
,
GenerateFlowChartModuleVisitor
(
,
).
(
));
}
void
(
*
)
override
{
->
(
this
);
}
void
(
*
)
override
{
->
(
static_cast
<
::
*>(
this
));
}
void
(
*
)
override
{
=
(
,
,
::
);
=
;
if
(
->
)
{
AppendUnawaredCopiedStatement(catchNode, scopeContext, COPY_AST(node->statement));
AppendUnawaredCopiedStatement
(
,
,
GenerateFlowChartModuleVisitor
(
,
).
(
->
));
}
=
(
,
);
{
auto
=
<
>();
((
<
>)
pauseStat
,
->
);
->
.
(
pauseStat
);
}
=
(
,
);
->
=
;
}
void
(
*
)
override
{
CHECK_FAIL(L"GenerateFlowChartStatementVisitor::Visit(WfCoOperatorStatement*)#Internal error, co-operator statement is not allowed in $coroutine expression.");
do
{
throw
(
L"GenerateFlowChartStatementVisitor::Visit(WfCoOperatorStatement*)#Internal error, co-operator statement is not allowed in $coroutine expression."
);}
while
(
0
);
}
void
(
*
)
override
{
CHECK_FAIL(L"GenerateFlowChartStatementVisitor::Visit(WfStateMachineStatement*)#Internal error, state machine statement is not allowed in $coroutine expression.");
do
{
throw
(
L"GenerateFlowChartStatementVisitor::Visit(WfStateMachineStatement*)#Internal error, state machine statement is not allowed in $coroutine expression."
);}
while
(
0
);
}
#undef COPY_STATEMENT
};
<
>
(
*
,
<
*>&
,
<
*>&
,
<
*,
>&
,
<
>
)
{
auto
=
<
>();
<
*>
;
(
sortedAwaredStatements
,
,
true
);
(
sortedAwaredStatements
,
,
true
);
auto
=
flowChart
(
nullptr
);
GenerateFlowChartStatementVisitor
::
;
context
.
=
endNode
;
auto
=
GenerateFlowChartStatementVisitor
::
(
,
sortedAwaredStatements
,
,
flowChart
,
nullptr
,
nullptr
, &
context
,
);
pair
.
->
=
endNode
;
flowChart
=
pair
.
;
flowChart
=
endNode
;
return
flowChart
;
}
void
(
<
>
,
<
*,
>&
)
{
const
auto
&
=
.
();
auto
&
=
const_cast
<
<
*,
>::
&>(
.
());
FOREACH(Ptr<FlowChartNode>, node, flowChart->nodes)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
node
);)
{
.
(
node
.
(),
0
);
}
.
(
,
1
);
auto
= [&](
*
)
{
if
(
node
)
{
=
keys
.
(
node
);
values
index
]++;
}
};
FOREACH(Ptr<FlowChartNode>, node, flowChart->nodes)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
node
);)
{
Inc
(
node
);
Inc
(
node
);
Inc
(
node
);
FOREACH(Ptr<FlowChartBranch>, branch, node->branches)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
node
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
branch
);)
{
Inc
(
branch
);
}
}
}
void
RemoveUnnecessaryNodesPass
(
<
>
)
{
<
*,
>
;
(
,
enterCounts
);
<
*>
;
<
<
>>
;
FOREACH(Ptr<FlowChartNode>, node, flowChart->nodes)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
node
);)
{
bool
=
false
;
if
(
node
.
() ==
0
&&
node
)
{
if
(
node
.
() ==
0
&&
node
==
::
&& !
node
)
{
mergable
=
true
;
}
else
if
(
node
->
==
::
&& !
node
->
&&
enterCounts
node
] ==
1
)
{
mergable
=
true
;
}
}
if
(
mergable
)
{
mergableNodes
.
(
node
.
());
}
else
{
keepingNodes
.
(
node
);
}
}
<
*,
*>
;
FOREACH(FlowChartNode*, node, mergableNodes)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
*>&
= ::
vl
::
collections
::
(
mergableNodes
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
*
;
__foreach_iterator__
.
(
node
);)
{
auto
=
node
;
while
(
mergableNodes
.
(
current
))
{
auto
=
current
->
;
if
(
current
->
==
::
)
{
target
->
=
current
->
;
target
->
=
current
->
;
}
if
(
current
->
)
{
target
->
=
current
->
;
}
if
(
current
->
.
() >
0
)
{
(
current
->
,
target
->
,
true
);
(
target
->
,
current
->
);
current
->
.
();
}
current
=
target
;
}
merging
.
(
node
,
current
);
}
#define MERGE_FLOW_CHART_NODE(DESTINATION)\
{\
vint index = merging.Keys().IndexOf(DESTINATION);\
if (index != -1) DESTINATION = merging.Values()[index];\
}\
FOREACH(Ptr<FlowChartNode>, node, flowChart->nodes)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
node
);)
{
if
(!
mergableNodes
.
(
node
.
()))
{
MERGE_FLOW_CHART_NODE(node->destination);
{
=
merging
.
().
(
node
);
if
(
index
!= -
1
)
node
=
merging
.
()
index
]; };
MERGE_FLOW_CHART_NODE(node->exceptionDestination);
{
=
merging
.
().
(
node
);
if
(
index
!= -
1
)
node
=
merging
.
()
index
]; };
MERGE_FLOW_CHART_NODE(node->pauseDestination);
{
=
merging
.
().
(
node
);
if
(
index
!= -
1
)
node
=
merging
.
()
index
]; };
FOREACH(Ptr<FlowChartBranch>, branch, node->branches)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
node
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
branch
);)
{
MERGE_FLOW_CHART_NODE(branch->destination);
{
=
merging
.
().
(
branch
);
if
(
index
!= -
1
)
branch
=
merging
.
()
index
]; };
}
}
}
MERGE_FLOW_CHART_NODE(flowChart->headNode);
{
=
merging
.
().
(
);
if
(
index
!= -
1
)
=
merging
.
()
index
]; };
MERGE_FLOW_CHART_NODE(flowChart->lastNode);
{
=
merging
.
().
(
);
if
(
index
!= -
1
)
=
merging
.
()
index
]; };
#undef MERGE_FLOW_CHART_NODE
=
keepingNodes
.
(
);
if
(
headNodeIndex
!=
0
)
{
auto
=
keepingNodes
headNodeIndex
];
keepingNodes
.
(
headNodeIndex
);
keepingNodes
.
(
0
,
headNode
);
}
(
,
keepingNodes
);
}
void
(
<
>
)
{
RemoveUnnecessaryNodesPass
(
);
FOREACH(Ptr<FlowChartNode>, node, flowChart->nodes)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
node
);)
{
if
(
node
&&
node
.
() >
0
&&
node
node
.
() -
1
].
<
>())
{
node
=
nullptr
;
}
}
<
*,
>
;
(
,
enterCounts
);
FOREACH(Ptr<FlowChartNode>, node, flowChart->nodes)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
node
);)
{
FOREACH(Ptr<FlowChartBranch>, branch, node->branches)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
node
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
branch
);)
{
if
(
enterCounts
branch
] ==
1
)
{
branch
->
=
true
;
}
}
}
}
<
>
(
const
&
)
{
auto
=
<
>();
refExpr
.
;
auto
=
<
>();
funcExpr
.
=
L"SetStatus"
;
auto
=
<
>();
callExpr
funcExpr
;
callExpr
.
(
refExpr
);
auto
=
<
>();
stat
callExpr
;
return
stat
;
};
<
>
GenerateSetCoStateBeforePause
()
{
auto
=
<
>();
refBefore
.
=
L"<co-state-before-pause>"
;
auto
=
<
>();
refState
.
=
L"<co-state>"
;
auto
=
<
>();
assignExpr
=
::
;
assignExpr
refBefore
;
assignExpr
refState
;
auto
=
<
>();
stat
assignExpr
;
return
stat
;
}
<
>
GenerateSetCoStateBeforePauseToInvalid
()
{
auto
=
<
>();
refBefore
.
=
L"<co-state-before-pause>"
;
auto
=
<
>();
assignExpr
=
::
;
assignExpr
refBefore
;
assignExpr
GenerateCoroutineInvalidId
();
auto
=
<
>();
stat
assignExpr
;
return
stat
;
}
<
>
(
<
*>&
,
*
)
{
auto
=
<
>();
refState
.
=
L"<co-state>"
;
auto
=
<
>();
intState
.
(
.
(
));
auto
=
<
>();
assignExpr
=
::
;
assignExpr
refState
;
assignExpr
intState
;
auto
=
<
>();
stat
assignExpr
;
return
stat
;
};
<
>
ExpandExceptionDestination
(
*
,
<
*,
>&
,
<
*>&
,
<
>
)
{
auto
=
<
>();
auto
=
<
>();
nodeTryStat
nodeBlock
;
nodeTryStat
.
=
L"<co-ex>"
;
auto
=
<
>();
nodeTryStat
catchBlock
;
{
auto
=
<
>();
refTarget
.
->
];
auto
=
<
>();
refEx
.
=
L"<co-ex>"
;
auto
=
<
>();
assignExpr
=
::
;
assignExpr
refTarget
;
assignExpr
refEx
;
auto
=
<
>();
stat
assignExpr
;
catchBlock
.
(
stat
);
}
catchBlock
.
(
(
,
));
catchBlock
.
(
<
>());
.
(
nodeTryStat
);
return
nodeBlock
;
}
void
(
<
>
,
*
,
<
*,
>&
,
<
*>&
,
*
,
<
>
)
{
if
(
->
==
::
)
{
.
(
(
L"Waiting"
));
.
(
GenerateSetCoStateBeforePause
());
.
(
(
,
->
));
}
auto
=
;
if
(
->
&&
!=
->
)
{
nodeBlock
ExpandExceptionDestination
(
->
,
,
,
);
}
bool
=
false
;
FOREACH(Ptr<WfStatement>, stat, flowChartNode->statements)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
stat
);)
{
if
(
stat
.
<
>())
{
exited
=
true
;
nodeBlock
.
(
<
>());
}
else
if
(
stat
.
<
>())
{
exited
=
true
;
.
(
(
L"Stopped"
));
{
auto
=
<
>();
.
(
returnStat
);
}
}
else
{
if
(
stat
.
<
WfRaiseExceptionStatement
>())
{
exited
=
true
;
}
nodeBlock
.
(
stat
);
}
}
FOREACH(Ptr<FlowChartBranch>, branch, flowChartNode->branches)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
branch
);)
{
<
>
;
if
(
branch
)
{
auto
=
<
>();
ifStat
branch
;
trueBlock
<
>();
ifStat
trueBlock
;
nodeBlock
.
(
ifStat
);
}
else
{
trueBlock
nodeBlock
;
}
if
(
branch
->
)
{
(
,
branch
,
,
,
->
,
trueBlock
);
}
else
{
trueBlock
.
(
(
,
branch
));
trueBlock
.
(
<
>());
}
}
if
(!
exited
)
{
if
(
==
)
{
.
(
(
L"Stopped"
));
{
auto
=
<
>();
.
(
returnStat
);
}
}
else
{
.
(
(
,
->
));
.
(
<
>());
}
}
}
void
ExpandNewCoroutineExpression
(
*
,
*
)
{
<
*>
;
<
*>
;
<
*,
>
;
FindCoroutineAwaredStatements
(
->
,
awaredStatements
);
FOREACH(WfStatement*, stat, awaredStatements)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
*>&
= ::
vl
::
collections
::
(
awaredStatements
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
*
;
__foreach_iterator__
.
(
stat
);)
{
FindCoroutineAwaredVariables
(
stat
,
awaredVariables
);
}
FindCoroutineReferenceRenaming
(
,
awaredStatements
,
awaredVariables
,
referenceRenaming
);
auto
=
(
,
awaredStatements
,
awaredVariables
,
referenceRenaming
,
->
);
(
flowChart
);
<
*>
;
(
nodeOrders
,
(
flowChart
)
.Select([](
<
>
)
{
return
node
.
();
})
.Where([](
*
)
{
return
!
node
->
;
})
);
auto
=
<
>();
->
newExpr
;
newExpr
(
<
<
>>::
().
());
FOREACH(WfLexicalSymbol*, symbol,
From(referenceRenaming.Keys())
.OrderBy([&](WfLexicalSymbol* a, WfLexicalSymbol* b)
{
return WString::Compare(referenceRenaming[a], referenceRenaming[b]);
}))
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
*>&
= ::
vl
::
collections
::
(
(
referenceRenaming
.
()) .
([&](
*
,
*
) {
return
::
(
referenceRenaming
a
],
referenceRenaming
b
]); }));
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
*
;
__foreach_iterator__
.
(
symbol
);)
{
auto
=
<
>();
newExpr
.
(
varDecl
);
{
auto
=
<
>();
member
=
::
;
varDecl
member
;
}
varDecl
.
referenceRenaming
symbol
];
varDecl
(
symbol
->
.
());
varDecl
(
symbol
->
.
());
}
{
auto
=
<
>();
newExpr
.
(
varDecl
);
{
auto
=
<
>();
member
=
::
;
varDecl
member
;
}
varDecl
.
=
L"<co-state>"
;
varDecl
(
<
>::
().
());
auto
=
<
>();
stateExpr
.
=
L"0"
;
varDecl
stateExpr
;
}
{
auto
=
<
>();
newExpr
.
(
varDecl
);
{
auto
=
<
>();
member
=
::
;
varDecl
member
;
}
varDecl
.
=
L"<co-state-before-pause>"
;
varDecl
(
<
>::
().
());
varDecl
GenerateCoroutineInvalidId
();
}
{
auto
=
<
WfAutoPropertyDeclaration
>();
newExpr
.
(
propDecl
);
{
auto
=
<
>();
member
=
::
;
propDecl
member
;
}
propDecl
.
=
L"Failure"
;
propDecl
(
<
<
>>::
().
());
propDecl
=
::
;
propDecl
=
::
;
auto
=
<
>();
nullExpr
=
::
;
propDecl
nullExpr
;
}
{
auto
=
<
WfAutoPropertyDeclaration
>();
newExpr
.
(
propDecl
);
{
auto
=
<
>();
member
=
::
;
propDecl
member
;
}
propDecl
.
=
L"Status"
;
propDecl
(
<
>::
().
());
propDecl
=
::
;
propDecl
=
::
;
auto
=
<
>();
refExpr
.
=
L"Waiting"
;
propDecl
refExpr
;
}
=
->
.
==
L""
?
L"<coroutine-output>"
:
->
.
;
{
auto
=
<
>();
newExpr
.
(
funcDecl
);
{
auto
=
<
>();
member
=
::
;
funcDecl
member
;
}
funcDecl
=
::
;
funcDecl
.
=
L"Resume"
;
funcDecl
(
<
void
>::
().
());
{
auto
=
<
>();
funcDecl
.
(
argument
);
argument
.
=
L"<raise-exception>"
;
argument
(
<
bool
>::
().
());
}
{
auto
=
<
>();
funcDecl
.
(
argument
);
argument
.
coResultName
;
argument
(
<
<
>>::
().
());
}
auto
=
<
>();
funcDecl
block
;
{
auto
=
<
>();
{
auto
=
<
>();
refStatus
.
=
L"Status"
;
auto
=
<
>();
waitingStatus
GetExpressionFromTypeDescriptor
(
description
::
<
>());
waitingStatus
.
=
L"Waiting"
;
auto
=
<
>();
compExpr
=
::
;
compExpr
refStatus
;
compExpr
waitingStatus
;
ifStat
compExpr
;
}
auto
=
<
>();
ifStat
trueBlock
;
{
auto
=
<
>();
exExpr
.
=
L"Resume should be called only when the coroutine is in the waiting status."
;
auto
=
<
WfRaiseExceptionStatement
>();
raiseStat
exExpr
;
trueBlock
.
(
raiseStat
);
}
block
.
(
ifStat
);
}
block
.
(
(
L"Executing"
));
{
auto
=
<
>();
auto
=
<
>();
tryStat
tryBlock
;
{
auto
=
<
>();
{
auto
=
<
>();
refBefore
.
=
L"<co-state-before-pause>"
;
auto
=
<
>();
compareInput
=
::
;
compareInput
refBefore
;
compareInput
GenerateCoroutineInvalidId
();
auto
=
<
>();
tryBlock
.
(
ifStat
);
ifStat
compareInput
;
ifStat
trueBlock
;
}
{
auto
=
<
>();
<
>*
=
nullptr
;
auto
=
<
>();
auto
=
<
>();
{
auto
=
<
>();
refOutput
.
coResultName
;
auto
=
<
>();
testNullExpr
=
::
;
testNullExpr
refOutput
;
auto
=
<
>();
trueBlock
.
(
ifStat
);
ifStat
testNullExpr
;
ifStat
nullTrueBlock
;
nullTrueBlock
.
(
GenerateSetCoStateBeforePauseToInvalid
());
nullFalseBlock
= &
ifStat
;
}
{
auto
=
<
>();
refOutput
.
coResultName
;
auto
=
<
>();
refFailure
refOutput
;
refFailure
.
=
L"Failure"
;
auto
=
<
>();
testNullExpr
=
::
;
testNullExpr
refFailure
;
auto
=
<
>();
*
nullFalseBlock
ifStat
;
ifStat
testNullExpr
;
ifStat
exTrueBlock
;
exTrueBlock
.
(
GenerateSetCoStateBeforePauseToInvalid
());
ifStat
exFalseBlock
;
}
{
<
>
;
<
>*
= &
firstIfStatement
;
using
=
<
*,
<
*>>;
auto
=
(
nodeOrders
)
.GroupBy([](
*
)
{
return
node
->
;
})
.OrderBy([&](
const
&
,
const
&
)
{
return
nodeOrders
.
(
p1
.
) -
nodeOrders
.
(
p2
.
);
});
FOREACH(GroupPair, group, nodeByCatches)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
nodeByCatches
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
group
);)
{
auto
=
group
.
;
if
(!
catchNode
)
continue
;
<
>
;
{
<
<
,
>>
;
FOREACH(FlowChartNode*, flowChartNode, group.value)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
*>&
= ::
vl
::
collections
::
(
group
.
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
*
;
__foreach_iterator__
.
(
flowChartNode
);)
{
=
nodeOrders
.
(
flowChartNode
);
if
(
conditionRanges
.
() ==
0
)
{
conditionRanges
.
({
state
,
state
});
}
else
if
(
conditionRanges
conditionRanges
.
() -
1
].f1 ==
state
-
1
)
{
conditionRanges
conditionRanges
.
() -
1
].f1 =
state
;
}
else
{
conditionRanges
.
({
state
,
state
});
}
}
for
(
=
0
;
i
<
conditionRanges
.
();
i
++)
{
auto
=
conditionRanges
i
];
<
>
;
if
(
range
.f0 ==
range
.f1)
{
auto
=
<
>();
refState
.
=
L"<co-state-before-pause>"
;
auto
=
<
>();
intState
.
=
(
range
.f0);
auto
=
<
>();
compExpr
=
::
;
compExpr
refState
;
compExpr
intState
;
singleCondition
compExpr
;
}
else
{
auto
=
<
>();
refState
.
=
L"<co-state-before-pause>"
;
auto
=
<
>();
intState1
.
=
(
range
.f0);
auto
=
<
>();
intState2
.
=
(
range
.f1);
auto
=
<
>();
rangeExpr
intState1
;
rangeExpr
=
::
;
rangeExpr
intState2
;
rangeExpr
=
::
;
auto
=
<
>();
compExpr
=
::
;
compExpr
refState
;
compExpr
rangeExpr
;
singleCondition
compExpr
;
}
if
(
condition
)
{
auto
=
<
>();
orExpr
=
::
;
orExpr
condition
;
orExpr
singleCondition
;
condition
orExpr
;
}
else
{
condition
singleCondition
;
}
}
}
auto
=
<
>();
*
currentIfVar
ifStat
;
currentIfVar
= &
ifStat
;
ifStat
condition
;
auto
=
<
>();
ifStat
catchBlock
;
catchBlock
.
(
GenerateSetCoStateBeforePauseToInvalid
());
{
auto
=
<
>();
refTarget
.
referenceRenaming
catchNode
->
];
auto
=
<
>();
refOutput
.
coResultName
;
auto
=
<
>();
refFailure
refOutput
;
refFailure
.
=
L"Failure"
;
auto
=
<
>();
assignExpr
=
::
;
assignExpr
refTarget
;
assignExpr
refFailure
;
auto
=
<
>();
stat
assignExpr
;
catchBlock
.
(
stat
);
}
catchBlock
.
(
(
nodeOrders
,
catchNode
));
}
{
auto
=
<
>();
*
currentIfVar
block
;
block
.
(
GenerateSetCoStateBeforePauseToInvalid
());
{
auto
=
<
>();
refOutput
.
coResultName
;
auto
=
<
>();
refFailure
refOutput
;
refFailure
.
=
L"Failure"
;
auto
=
<
WfRaiseExceptionStatement
>();
raiseStat
refFailure
;
block
.
(
raiseStat
);
}
}
exFalseBlock
.
(
firstIfStatement
);
}
}
}
{
auto
=
<
>();
{
auto
=
<
>();
trueExpr
=
::
;
whileStat
trueExpr
;
}
auto
=
<
>();
whileStat
whileBlock
;
using
=
<
*,
<
*>>;
auto
=
(
nodeOrders
)
.GroupBy([](
*
)
{
return
node
->
;
})
.OrderBy([&](
const
&
,
const
&
)
{
return
nodeOrders
.
(
p1
.
) -
nodeOrders
.
(
p2
.
);
});
FOREACH(GroupPair, group, nodeByCatches)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
nodeByCatches
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
group
);)
{
auto
=
group
.
;
auto
=
whileBlock
;
if
(
catchNode
)
{
groupBlock
ExpandExceptionDestination
(
catchNode
,
referenceRenaming
,
nodeOrders
,
whileBlock
);
}
FOREACH(FlowChartNode*, flowChartNode, group.value)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
*>&
= ::
vl
::
collections
::
(
group
.
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
*
;
__foreach_iterator__
.
(
flowChartNode
);)
{
auto
=
<
>();
groupBlock
.
(
ifStat
);
{
auto
=
<
>();
refState
.
=
L"<co-state>"
;
auto
=
<
>();
intState
.
(
nodeOrders
.
(
flowChartNode
));
auto
=
<
>();
compExpr
=
::
;
compExpr
refState
;
compExpr
intState
;
ifStat
compExpr
;
}
auto
=
<
>();
ifStat
stateBlock
;
{
(
flowChart
,
flowChartNode
,
referenceRenaming
,
nodeOrders
,
catchNode
,
stateBlock
);
}
}
}
tryBlock
.
(
whileStat
);
}
tryStat
.
=
L"<co-ex>"
;
auto
=
<
>();
tryStat
catchBlock
;
{
auto
=
<
>();
refExpr
.
=
L"<co-ex>"
;
auto
=
<
>();
funcExpr
.
=
L"SetFailure"
;
auto
=
<
>();
callExpr
funcExpr
;
callExpr
.
(
refExpr
);
auto
=
<
>();
stat
callExpr
;
catchBlock
.
(
stat
);
}
catchBlock
.
(
(
L"Stopped"
));
{
auto
=
<
>();
refExpr
.
=
L"<raise-exception>"
;
auto
=
<
>();
ifStat
refExpr
;
auto
=
<
>();
ifStat
trueBlock
;
{
auto
=
<
WfRaiseExceptionStatement
>();
trueBlock
.
(
raiseStat
);
}
catchBlock
.
(
ifStat
);
}
block
.
(
tryStat
);
}
}
}
void
ExpandCoOperatorExpression
(
*
,
*
)
{
auto
=
->
].
();
auto
=
scope
->
();
auto
=
functionScope
->
.
<
>();
auto
=
->
newCoExpr
.
()].
;
auto
=
GetExpressionFromTypeDescriptor
(
providerType
());
auto
=
<
>();
refQueryContext
refProvider
;
refQueryContext
.
=
L"QueryContext"
;
auto
=
<
>();
refImpl
.
=
L"<co-impl>"
;
auto
=
<
>();
refCall
refQueryContext
;
refCall
.
(
refImpl
);
auto
=
<
>();
refOperator
refCall
;
refOperator
.
->
.
;
->
refOperator
;
}
}
}
}