private static TypeDefinition buildTypeOfLambda(ComputationContext ctx,
                                                        FunctionDefinition lambda, IEnumerable <VariableDeclaration> fields)
        {
            if (lambda.Owner != null)
            {
                throw new Exception("Internal error");
            }

            FunctionDefinition cons = FunctionDefinition.CreateInitConstructor(EntityModifier.None,
                                                                               fields.Select(it => FunctionParameter.Create(it.Name.Name, it.TypeName)),
                                                                               Block.CreateStatement(
                                                                                   fields.Select(it
                                                                                                 => Assignment.CreateStatement(NameReference.Create(NameFactory.ThisVariableName, it.Name.Name),
                                                                                                                               NameReference.Create(it.Name.Name)))
                                                                                   ));

            lambda.SetModifier(EntityModifier.Override | lambda.Modifier);

            TypeDefinition functor = TypeBuilder.Create(NameDefinition.Create(AutoName.Instance.CreateNew("Closure")))
                                     .With(fields)
                                     .With(cons)
                                     .With(lambda)
                                     .Parents(lambda.CreateFunctionInterface());

            return(functor);
        }
        private static TypeDefinition buildTypeOfReference(ComputationContext ctx,
                                                           NameReference funcReference, IExpression thisObject)
        {
            if (funcReference.Owner != null)
            {
                throw new Exception("Detach it first.");
            }

            const string meta_this = "mThis";

            FunctionDefinition function = funcReference.Binding.Match.Instance.Target.CastFunction();

            FunctionDefinition cons;
            NameReference      func_field_ref;

            if (thisObject != null)
            {
                cons = FunctionDefinition.CreateInitConstructor(EntityModifier.None,
                                                                new[] { FunctionParameter.Create(meta_this, thisObject.Evaluation.Components.NameOf) },
                                                                Block.CreateStatement(
                                                                    new[] {
                    Assignment.CreateStatement(NameReference.Create(NameFactory.ThisVariableName, meta_this),
                                               NameReference.Create(meta_this)),
                }));

                func_field_ref = NameReference.Create(NameFactory.ThisVariableName, meta_this);
            }
            else
            {
                func_field_ref = null;
                cons           = null;
            }

            IEnumerable <FunctionParameter> trans_parameters = function.Parameters.Select(pit =>
                                                                                          FunctionParameter.Create(pit.Name.Name, pit.TypeName.Evaluated(ctx, EvaluationCall.AdHocCrossJump)
                                                                                                                   .TranslateThrough(funcReference.Binding.Match.Instance).NameOf));
            FunctionDefinition invoke = FunctionBuilder.Create(NameFactory.LambdaInvoke, ExpressionReadMode.ReadRequired,
                                                               function.ResultTypeName,
                                                               Block.CreateStatement(new[] {
                Return.Create(FunctionCall.Create(
                                  NameReference.Create(func_field_ref, funcReference.Name,
                                                       funcReference.TemplateArguments.Select(it => it.TypeName).ToArray()),
                                  function.Parameters.Select(it => FunctionArgument.Create(NameReference.Create(it.Name.Name))).ToArray()))
            }))
                                        .SetModifier(EntityModifier.Override)
                                        .Parameters(trans_parameters.ToArray());


            TypeBuilder closure_builder = TypeBuilder.Create(NameDefinition.Create(AutoName.Instance.CreateNew("Closure")))
                                          .With(invoke)
                                          .Parents(invoke.CreateFunctionInterface());

            if (thisObject != null)
            {
                VariableDeclaration this_field = VariableDeclaration.CreateStatement(meta_this,
                                                                                     thisObject.Evaluation.Components.NameOf, Undef.Create());
                closure_builder
                .With(cons)
                .With(this_field);

                TypeMutability mutability = thisObject.Evaluation.Components.MutabilityOfType(ctx);
                if (mutability == TypeMutability.ForceMutable)
                {
                    closure_builder.SetModifier(EntityModifier.Mutable);
                }
                else if (mutability != TypeMutability.ConstAsSource)
                {
                    throw new NotImplementedException();
                }
            }

            return(closure_builder);
        }