#include "WfEmitter.h"
namespace
{
namespace
{
namespace
{
using
namespace
collections
;
using
namespace
reflection
;
using
namespace
reflection
::
description
;
using
namespace
analyzer
;
using
namespace
runtime
;
typedef
;
#define INSTRUCTION(X) context.AddInstruction(node, X)
#define FILL_LABEL_TO_INS(LABEL, INS) context.assembly->instructions[LABEL].indexParameter = INS
#define FILL_LABEL_TO_CURRENT(LABEL) FILL_LABEL_TO_INS(LABEL, context.assembly->instructions.Count())
#define EXIT_CODE(X) context.AddExitInstruction(node, X)
class
GenerateStatementInstructionsVisitor
:
public
,
public
::
{
public
:
&
;
GenerateStatementInstructionsVisitor
(
&
)
:context(
)
{
}
void
(
<
>
)
{
.
(
);
if
(
)
{
GenerateStatementInstructions
(
,
);
}
}
void
ApplyCurrentScopeExitCode
()
{
auto
=
.
();
(
scopeContext
);
}
void
(
,
bool
,
const
&
=
::
)
{
=
.
.
() -
1
;
while
(
index
>=
0
)
{
auto
=
.
index
];
bool
=
false
;
if
(
scopeContext
==
)
{
if
(
L""
||
scopeContext
==
)
{
found
=
true
;
}
}
if
(
&&
found
)
break
;
(
scopeContext
);
if
(!
&&
found
)
break
;
index
--;
}
}
void
(
*
)
override
{
(
::
,
false
);
context.functionContext->GetCurrentScopeContext(WfCodegenScopeType::Loop)->breakInstructions.Add(INSTRUCTION(Ins::Jump(-1)));
}
void
(
*
)
override
{
(
::
,
true
);
context.functionContext->GetCurrentScopeContext(WfCodegenScopeType::Loop)->continueInstructions.Add(INSTRUCTION(Ins::Jump(-1)));
}
void
(
*
)
override
{
(
::
,
false
);
if
(
->
)
{
GenerateExpressionInstructions
(
,
->
);
}
else
{
INSTRUCTION(Ins::LoadValue({}));
}
INSTRUCTION(Ins::Return());
}
void
(
*
)
override
{
GenerateExpressionInstructions
(
,
->
);
INSTRUCTION(Ins::DeleteRawPtr());
}
void
(
WfRaiseExceptionStatement
*
)
override
{
if
(
->
)
{
GenerateExpressionInstructions
(
,
->
);
}
else
{
auto
=
.
->
];
while
(
scope
)
{
if
(
auto
=
scope
.
<
>())
{
if
(
tryCatch
.
!=
L""
)
{
auto
=
scope
tryCatch
.
]
0
].
();
=
.
symbol
];
INSTRUCTION(Ins::LoadLocalVar(index));
break
;
}
}
scope
scope
;
}
}
INSTRUCTION(Ins::RaiseException());
}
void
(
*
)
override
{
= -
1
;
GenerateExpressionInstructions
(
,
->
);
if
(
->
.
!=
L""
)
{
auto
=
.
->
];
auto
=
scope
->
.
]
0
];
auto
=
.
;
variableIndex
=
function
.
() +
function
.
(
L"<if>"
+
->
.
);
.
.
(
symbol
.
(),
variableIndex
);
GenerateTypeCastInstructions
(
,
symbol
,
false
,
->
.
());
INSTRUCTION(Ins::StoreLocalVar(variableIndex));
INSTRUCTION(Ins::LoadLocalVar(variableIndex));
INSTRUCTION(Ins::LoadValue({}));
INSTRUCTION(Ins::CompareReference());
}
else
{
INSTRUCTION(Ins::OpNot(WfInsType::Bool));
}
vint fillElseIndex = INSTRUCTION(Ins::JumpIf(-1));
GenerateStatementInstructions
(
,
->
);
if
(
variableIndex
!= -
1
)
{
INSTRUCTION(Ins::LoadValue({}));
INSTRUCTION(Ins::StoreLocalVar(variableIndex));
}
vint fillEndIndex = INSTRUCTION(Ins::Jump(-1));
FILL_LABEL_TO_CURRENT(fillElseIndex);
if
(
->
)
{
GenerateStatementInstructions
(
,
->
);
}
FILL_LABEL_TO_CURRENT(fillEndIndex);
}
void
(
*
)
override
{
= -
1
;
= -
1
;
= -
1
;
auto
=
.
(
::
);
loopLabelIndex
=
.
.
();
continueLabelIndex
=
.
.
();
GenerateExpressionInstructions
(
,
->
);
INSTRUCTION(Ins::OpNot(WfInsType::Bool));
loopContext->breakInstructions.Add(INSTRUCTION(Ins::JumpIf(-1)));
loopContext
.
(
.
(
,
::
(-
1
)));
GenerateStatementInstructions
(
,
->
);
INSTRUCTION(Ins::Jump(loopLabelIndex));
breakLabelIndex
=
.
.
();
FOREACH(vint, index, loopContext->continueInstructions)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
loopContext
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
index
);)
{
FILL_LABEL_TO_INS(index, continueLabelIndex);
.
index
].
=
continueLabelIndex
;
}
FOREACH(vint, index, loopContext->breakInstructions)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
loopContext
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
index
);)
{
FILL_LABEL_TO_INS(index, breakLabelIndex);
.
index
].
=
breakLabelIndex
;
}
.
();
}
<
,
>
(
*
,
<
>
,
<
>
)
{
auto
=
.
(
::
);
EXIT_CODE(Ins::UninstallTry(0));
catchContext
;
vint trap = INSTRUCTION(Ins::InstallTry(-1));
GenerateStatementInstructions
(
,
);
.
();
INSTRUCTION(Ins::UninstallTry(0));
vint finish = INSTRUCTION(Ins::Jump(-1));
return
{
trap
,
finish
};
}
GenerateExceptionVariable
(
*
)
{
*
=
nullptr
;
;
if
(
->
)
{
auto
=
.
->
].
();
exceptionSymbol
=
scope
->
->
.
]
0
].
();
exceptionName
=
L"<catch>"
+
->
.
;
}
else
{
exceptionName
=
L"<try-finally-exception>"
;
}
auto
=
.
;
=
function
.
() +
function
.
(
L"<catch>"
+
->
.
);
if
(
exceptionSymbol
)
{
.
.
(
exceptionSymbol
,
variableIndex
);
}
return
variableIndex
;
}
void
(
*
,
,
<
,
>
)
{
FILL_LABEL_TO_CURRENT(trap.key);
INSTRUCTION(Ins::LoadException());
INSTRUCTION(Ins::StoreLocalVar(variableIndex));
}
void
(
*
,
)
{
GenerateStatementInstructions
(
,
->
);
INSTRUCTION(Ins::LoadLocalVar(variableIndex));
INSTRUCTION(Ins::RaiseException());
}
void
(
*
)
override
{
auto
=
(
,
->
,
->
);
<
,
>
= { -
1
,-
1
};
auto
=
GenerateExceptionVariable
(
);
{
(
,
variableIndex
,
trap1
);
if
(
->
)
{
if
(
->
)
{
trap2
(
,
->
,
->
);
(
,
variableIndex
,
trap2
);
(
,
variableIndex
);
}
else
{
GenerateStatementInstructions
(
,
->
);
}
}
else
{
(
,
variableIndex
);
}
}
FILL_LABEL_TO_CURRENT(trap1.value);
if
(
trap2
.
!= -
1
)
{
FILL_LABEL_TO_CURRENT(trap2.value);
}
if
(
->
)
{
GenerateStatementInstructions
(
,
->
);
}
}
void
(
*
)
override
{
<
>
;
if
(
->
.
!=
L""
)
{
blockContext
.
(
::
,
->
.
);
}
FOREACH(Ptr<WfStatement>, statement, node->statements)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
<
>>&
= ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
<
>
;
__foreach_iterator__
.
(
statement
);)
{
GenerateStatementInstructions
(
,
statement
);
}
if
(
blockContext
)
{
=
.
.
();
FOREACH(vint, index, blockContext->breakInstructions)
if
(
bool
=
true
)
for
(
const
::
vl
::
collections
::
<
>&
= ::
vl
::
collections
::
(
blockContext
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
)
for
(
;
__foreach_iterator__
.
(
index
);)
{
FILL_LABEL_TO_INS(index, breakLabelIndex);
.
index
].
=
breakLabelIndex
;
}
.
();
}
}
void
(
*
)
override
{
(
::
,
false
,
->
.
);
context.functionContext->GetCurrentScopeContext(WfCodegenScopeType::Block, node->label.value)->breakInstructions.Add(INSTRUCTION(Ins::Jump(-1)));
.
(
::
,
->
.
)
.
(
.
(
,
::
(-
1
)));
}
void
(
*
)
override
{
GenerateExpressionInstructions
(
,
->
);
}
void
(
*
)
override
{
auto
=
.
;
auto
=
manager
->
->
.
()];
auto
=
scope
->
.
]
0
].
();
auto
=
.
;
=
function
.
() +
function
.
(
->
.
);
.
.
(
symbol
,
index
);
GenerateExpressionInstructions
(
,
->
);
INSTRUCTION(Ins::StoreLocalVar(index));
}
void
(
*
)
override
{
GenerateStatementInstructions
(
,
->
);
}
void
(
*
)
override
{
CHECK_FAIL(L"GenerateStatementInstructionsVisitor::Visit(WfCoroutineStatement*)#Internal error, All coroutine statements do not emit instructions.");
do
{
throw
(
L"GenerateStatementInstructionsVisitor::Visit(WfCoroutineStatement*)#Internal error, All coroutine statements do not emit instructions."
);}
while
(
0
);
}
void
(
*
)
override
{
CHECK_FAIL(L"GenerateStatementInstructionsVisitor::Visit(WfStateMachineStatement*)#Internal error, All state machine statements do not emit instructions.");
do
{
throw
(
L"GenerateStatementInstructionsVisitor::Visit(WfStateMachineStatement*)#Internal error, All state machine statements do not emit instructions."
);}
while
(
0
);
}
};
#undef EXIT_CODE
#undef FILL_LABEL_TO_CURRENT
#undef FILL_LABEL_TO_INS
#undef INSTRUCTION
void
GenerateStatementInstructions
(
&
,
<
>
)
{
GenerateStatementInstructionsVisitor
(
);
(&
visitor
);
}
}
}
}