#include "WfEmitter.h"
namespace
 
{
	
namespace
 
	{
		
namespace
 
		{
			
using
 namespace
 collections
;
			
using
 namespace
 parsing
;
			
using
 namespace
 reflection
::
description
;
			
using
 namespace
 analyzer
;
			
using
 namespace
 runtime
;
			
using
 namespace
 typeimpl
;
			
typedef
  ;
#define INSTRUCTION(X) context.AddInstruction(node, X)
			class
 GenerateInitializeInstructionsVisitor
 : 
public
 , 
public
 ::
			{
			
public
:
				
&						
;
				
GenerateInitializeInstructionsVisitor
(
& 
)
					:context(
)
				{
				}
				
void
 (
* 
)
override
				{
					FOREACH(Ptr<WfDeclaration>, decl, node->declarations)
					if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
decl
);)
 
					{
						
GenerateInitializeInstructions
(
, 
decl
);
					}
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
					
auto
  = 
.
->
].
();
					
auto
  = 
scope
->
->
.
]
0
];
					
  = 
.
symbol
.
()];
					
GenerateExpressionInstructions
(
, 
->
);
					INSTRUCTION(Ins::StoreGlobalVar(variableIndex));
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
					FOREACH(Ptr<WfDeclaration>, decl, node->expandedDeclarations)
					if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
decl
);)
 
					{
						
decl
(
this
);
					}
				}
				
void
 (
* 
)
override
				{
					FOREACH(Ptr<WfDeclaration>, decl, node->expandedDeclarations)
					if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
decl
);)
 
					{
						
decl
(
this
);
					}
				}
			};
			
void
 GenerateInitializeInstructions
(
& 
, 
<
> 
)
			{
				
GenerateInitializeInstructionsVisitor
(
);
				
(&
visitor
);
			}
			
<
> 
GenerateFunctionInstructions_Prolog
(
& 
, 
* 
, 
<
> 
, 
<
> 
, 
<
> 
, 
const
 <
<
>>& 
, 
const
 <
<
>>& 
, 
* 
)
			{
				
auto
  = 
<
>();
				
functionContext
  ;
				
.
  functionContext
;
				{
					FOREACH_INDEXER(Ptr<WfLexicalSymbol>, argumentSymbol, index, argumentSymbols)
					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__
.
(
argumentSymbol
);
index
++)
 
					{
						
functionContext
.
(
argumentSymbol
.
(), 
index
);
					}
					FOREACH_INDEXER(Ptr<WfLexicalSymbol>, capturedSymbol, index, capturedSymbols)
					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__
.
(
capturedSymbol
);
index
++)
 
					{
						
functionContext
.
(
capturedSymbol
.
(), 
index
);
					}
				}
				
if
 (
)
				{
					
  = 
.
() + 
.
(
L"<recursive-lambda>"
 + 
);
					
functionContext
.
(
.
(), 
variableIndex
);
				}
					
				
 = 
.
.
();
				
if
 (
)
				{
					INSTRUCTION(Ins::LoadClosureContext());
					INSTRUCTION(Ins::LoadFunction(context.assembly->functions.IndexOf(meta.Obj())));
					INSTRUCTION(Ins::CreateClosure());
					INSTRUCTION(Ins::StoreLocalVar(functionContext->localVariables[recursiveLambdaSymbol.Obj()]));
					.
(
, 
::
(
functionContext
.
()]));
 
				}
				
return
 functionContext
;
			}
			
void
 GenerateFunctionInstructions_Epilog
(
& 
, 
* 
, 
<
> 
, 
<
> 
, 
<
> 
, 
const
 <
<
>>& 
, 
const
 <
<
>>& 
, 
<
> 
, 
* 
)
			{
				INSTRUCTION(Ins::LoadValue({}));
				INSTRUCTION(Ins::Return());
 = 
.
.
() - 
1
;
				
.
  0
;
				
GenerateClosureInstructions
(
, 
);
			}
			
void
 GenerateFunctionInstructions
(
& 
, 
* 
, 
<
> 
, 
<
> 
, 
<
> 
, 
const
 <
<
>>& 
, 
const
 <
<
>>& 
, 
<
> 
, 
* 
)
			{
				
auto
  = 
GenerateFunctionInstructions_Prolog
(
, 
, 
, 
, 
, 
, 
, 
);
				
GenerateStatementInstructions
(
, 
);
				
GenerateFunctionInstructions_Epilog
(
, 
, 
, 
, 
, 
, 
, 
functionContext
, 
);
			}
			
void
 GenerateFunctionInstructions
(
& 
, 
* 
, 
<
> 
, 
<
> 
, 
<
> 
, 
const
 <
<
>>& 
, 
const
 <
<
>>& 
, 
<
> 
, 
* 
)
			{
				
auto
  = 
GenerateFunctionInstructions_Prolog
(
, 
, 
, 
, 
, 
, 
, 
);
				
GenerateExpressionInstructions
(
, 
);
				INSTRUCTION(Ins::Return());
GenerateFunctionInstructions_Epilog
(
, 
, 
, 
, 
, 
, 
, 
functionContext
, 
);
			}
			
void
 GenerateFunctionDeclarationInstructions
(
& 
, 
* 
, 
* 
, 
<
> 
, 
<
> 
)
			{
				
<
<
>> 
, 
;
				{
					FOREACH(Ptr<WfFunctionArgument>, argument, node->arguments)
					if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
argument
);)
 
					{
						
auto
  = 
->
argument
.
]
0
];
						
argumentSymbols
.
(
symbol
);
					}
					
  = 
.
->
.
().
(
);
					
if
 (
index
 != -
1
)
					{
						
auto
  = 
.
->
.
()
index
];
						FOREACH(Ptr<WfLexicalSymbol>, symbol, capture->symbols)
						if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
capture
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
symbol
);)
 
						{
							
capturedSymbols
.
(
symbol
);
						}
					}
				}
				
auto
  = 
(
, 
->
);
				
GenerateFunctionInstructions
(
, 
, 
, 
returnType
, 
, 
argumentSymbols
, 
capturedSymbols
, 
->
, 
);
			}
			
class
 GenerateClassMemberInstructionsVisitor
 : 
public
 , 
public
 ::
			{
			
public
:
				
&						
;
				
<
>					
;
				
GenerateClassMemberInstructionsVisitor
(
& 
, 
<
> 
)
					:context(
)
					, classDecl(
)
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
					
if
 (
->
 == 
::
)
					{
						
GenerateDeclarationInstructions
(
, 
);
					}
					
else
 if
 (
 == 
::
)
					{
						
GenerateDeclarationInstructions
(
, 
);
					}
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
class
 
					: 
public
 empty_visitor
::
				{
				
public
:
					
&					
;
					
(
& 
)
						:context(
)
					{
					}
					
void
 (
* 
)
override
					{
						FOREACH(Ptr<WfDeclaration>, decl, node->expandedDeclarations)
						if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
decl
);)
 
						{
							
decl
(
this
);
						}
					}
					
void
 (
* 
)
override
					{
						FOREACH(Ptr<WfDeclaration>, decl, node->expandedDeclarations)
						if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
decl
);)
 
						{
							
decl
(
this
);
						}
					}
					
void
 (
* 
)
override
					{
						
auto
  = 
.
->
].
<
>().
();
						
GenerateExpressionInstructions
(
, 
->
);
						INSTRUCTION(Ins::LoadCapturedVar(0));
						INSTRUCTION(Ins::SetProperty(info));
					}
				};
				
void
 (
* 
)
override
				{
					
auto
  = 
.
.
]];
					
auto
  = 
<
>();
					
functionContext
  meta
;
					
.
  functionContext
;
					
meta
 = 
.
.
();
					
					
auto
  = 
.
->
].
();
					{
						FOREACH_INDEXER(Ptr<WfFunctionArgument>, argument, index, node->arguments)
						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__
.
(
argument
);
index
++)
 
						{
							
auto
  = 
scope
->
argument
.
]
0
];
							
functionContext
.
(
symbol
.
(), 
index
);
						}
					}
					
if
 (
.
() > 
0
)
					{
						
auto
  = 
scope
->
;
						
  = 
td
->
GetBaseTypeDescriptorCount
();
						
for
 (
  = 
0
; 
i
 < 
count
; 
i
++)
						{
							
auto
  = 
td
->
(
i
);
							
auto
  = 
.
->
baseConstructorCallResolvings
{
, 
baseTd
}];
							
if
 (
ctor
.
)
							{
								FOREACH(Ptr<WfExpression>, argument, ctor.key->arguments)
								if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
ctor
.
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
argument
);)
 
								{
									
GenerateExpressionInstructions
(
, 
argument
);
								}
								INSTRUCTION(Ins::LoadCapturedVar(0));
								INSTRUCTION(Ins::InvokeBaseCtor(ctor.value, ctor.key->arguments.Count()));
								.
(
, 
::
(
ctor
.
, 
ctor
.
->
.
()));
 
							}
							
else
							{
								INSTRUCTION(Ins::LoadCapturedVar(0));
								INSTRUCTION(Ins::InvokeBaseCtor(ctor.value, 0));
							}
						}
					}
					{
						
 (
);
						FOREACH(Ptr<WfDeclaration>, memberDecl, classDecl->declarations)
						if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
memberDecl
);)
 
						{
							
memberDecl
(&
visitor
);
						}
					}
					
GenerateStatementInstructions
(
, 
->
);
					INSTRUCTION(Ins::LoadValue({}));
					INSTRUCTION(Ins::Return());
meta
 = 
.
.
() - 
1
;
					
.
  0
;
					
GenerateClosureInstructions
(
, 
functionContext
);
				}
				
				
void
 (
* 
)
override
				{
					
auto
  = 
.
.
]];
					
auto
  = 
<
>();
					
functionContext
  meta
;
					
.
  functionContext
;
					
meta
 = 
.
.
();
					
					
auto
  = 
.
->
].
();
					
GenerateStatementInstructions
(
, 
->
);
					INSTRUCTION(Ins::LoadValue({}));
					INSTRUCTION(Ins::Return());
meta
 = 
.
.
() - 
1
;
					
.
  0
;
					
GenerateClosureInstructions
(
, 
functionContext
);
				}
				
void
 (
* 
)
override
				{
					
GenerateDeclarationInstructions
(
, 
);
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
					FOREACH(Ptr<WfDeclaration>, decl, node->expandedDeclarations)
					if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
decl
);)
 
					{
						
decl
(
this
);
					}
				}
				
void
 (
* 
)
override
				{
					FOREACH(Ptr<WfDeclaration>, decl, node->expandedDeclarations)
					if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
decl
);)
 
					{
						
decl
(
this
);
					}
				}
			};
			
class
 GenerateDeclarationInstructionsVisitor
 : 
public
 , 
public
 ::
			{
			
public
:
				
&						
;
				
GenerateDeclarationInstructionsVisitor
(
& 
)
					:context(
)
				{
				}
				
void
 (
* 
)
override
				{
					FOREACH(Ptr<WfDeclaration>, decl, node->declarations)
					if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
decl
);)
 
					{
						
GenerateDeclarationInstructions
(
, 
decl
);
					}
				}
				
void
 (
* 
)
override
				{
					
auto
  = 
.
->
].
();
					
auto
  = 
.
->
(
scope
, 
);
					
auto
  = 
.
.
symbol
.
()]];
					
GenerateFunctionDeclarationInstructions
(
, 
, 
scope
, 
meta
, 
0
);
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
					FOREACH(Ptr<WfDeclaration>, memberDecl, node->declarations)
					if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
memberDecl
);)
 
					{
						
GenerateClassMemberInstructionsVisitor
(
, 
);
						
memberDecl
(&
visitor
);
					}
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
				}
				
void
 (
* 
)
override
				{
					FOREACH(Ptr<WfDeclaration>, decl, node->expandedDeclarations)
					if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
decl
);)
 
					{
						
decl
(
this
);
					}
				}
				
void
 (
* 
)
override
				{
					FOREACH(Ptr<WfDeclaration>, decl, node->expandedDeclarations)
					if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
->
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
decl
);)
 
					{
						
decl
(
this
);
					}
				}
			};
			
void
 GenerateDeclarationInstructions
(
& 
, 
<
> 
)
			{
				
GenerateDeclarationInstructionsVisitor
(
);
				
(&
visitor
);
			}
			
void
 GenerateClosureInstructions_Function
(
& 
, 
 , 
* 
, 
bool
 )
			{
				
auto
  = 
.
->
].
();
				
auto
  = 
.
];
				
GenerateFunctionDeclarationMetadata
(
, 
, 
meta
);
				
<
> 
;
				
if
 (!
 && 
->
.
 != 
L""
)
				{
					
recursiveLambdaSymbol
  scope
->
->
.
]
0
];
				}
				
GenerateFunctionDeclarationInstructions
(
, 
, 
scope
, 
meta
, 
recursiveLambdaSymbol
);
			}
			
void
 GenerateClosureInstructions_Ordered
(
& 
, 
 , 
WfOrderedLambdaExpression
* 
)
			{
				
auto
  = 
.
->
].
();
				
<
<
>> 
, 
;
				
(
					
argumentSymbols
,
					
<
>(
0
, 
scope
->
.
())
						.
([scope](
 )->
<
>{
return
 scope
->
.
(
index
)
0
];})
						.
([](
<
> 
, 
<
> 
)
						{
							
  = 
(
a
.
(
1
, 
a
.
() - 
1
));
							
  = 
(
b
.
(
1
, 
a
.
() - 
1
));
							
return
 aId
 - 
bId
;
						})
					);
				
auto
  = 
.
];
				FOREACH(Ptr<WfLexicalSymbol>, symbol, argumentSymbols)
				if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
argumentSymbols
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
symbol
);)
 
				{
					
meta
.
(
symbol
);
				}
				{
					
auto
  = 
.
->
.
(
);
					FOREACH(Ptr<WfLexicalSymbol>, symbol, capture->symbols)
					if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
capture
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
symbol
);)
 
					{
						
meta
.
(
L"<captured>"
 + 
symbol
);
						
capturedSymbols
.
(
symbol
);
					}
					
  = 
.
(
scope
);
					
for
 (
  = 
0
; 
i
 < 
count
; 
i
++)
					{
						
meta
.
(
L"<captured-this>"
 + 
(
i
));
					}
				}
				
auto
  = 
.
->
];
				
auto
  = 
(
result
.
()->
(
0
));
				
GenerateFunctionInstructions
(
, 
scope
, 
meta
, 
returnType
, 
0
, 
argumentSymbols
, 
capturedSymbols
, 
->
, 
);
			}
			
void
 GenerateClosureInstructions
(
& 
, 
<
> 
)
			{
				
for
 (
  = 
0
; 
i
 < 
.
(); 
i
++)
				{
					
  = 
.
()
i
];
					
auto
  = 
.
()
i
];
					
					
if
 (
closure
.
)
					{
						
GenerateClosureInstructions_Function
(
, 
functionIndex
, 
closure
.
->
.
(), 
false
);
					}
					
else
 if
 (
closure
.
)
					{
						
GenerateClosureInstructions_Ordered
(
, 
functionIndex
, 
closure
.
);
					}
					
else
 if
 (
closure
.
)
					{
						
GenerateClosureInstructions_Function
(
, 
functionIndex
, 
closure
.
, 
true
);
					}
				}
			}
#undef INSTRUCTION
		}
	}
}