コード例 #1
0
ファイル: MethodEmitter.cs プロジェクト: yaram/SharpVk
        private static void EmitActions(CodeBlockBuilder body, List <MethodAction> actions)
        {
            foreach (var action in actions.OfType <DeclarationAction>())
            {
                body.EmitVariableDeclaration(action.MemberType, action.MemberName, Default(action.MemberType));
            }

            foreach (var action in actions.OrderBy(x => x.Priority))
            {
                if (action is AssignAction assignAction)
                {
                    if (assignAction.IsLoop)
                    {
                        void BuildAssignBlock(CodeBlockBuilder ifBlock)
                        {
                            var fieldPointerName = assignAction.FieldPointerName ?? "fieldPointer";

                            if (assignAction.IsArray)
                            {
                                ifBlock.EmitVariableDeclaration("var", fieldPointerName, NewArray(assignAction.MemberType, Cast("uint", assignAction.LengthExpression)));
                            }
                            else
                            {
                                string allocationType = assignAction.MemberType.EndsWith("*")
                                                            ? "IntPtr"
                                                            : assignAction.MemberType;

                                ifBlock.EmitVariableDeclaration("var", fieldPointerName, Cast(assignAction.MemberType + "*", Call(StaticCall("Interop.HeapUtil", $"AllocateAndClear<{allocationType}>", assignAction.LengthExpression), "ToPointer")));
                            }

                            ifBlock.EmitForLoop(init => init.EmitVariableDeclaration("int", assignAction.IndexName, Literal(0)),
                                                LessThan(Variable(assignAction.IndexName), Cast("uint", assignAction.LengthExpression)),
                                                after => after.EmitStatement(assignAction.IndexName + "++"),
                                                loop =>
                            {
                                EmitMarshalAction(loop, assignAction, Index(Variable(fieldPointerName), Variable(assignAction.IndexName)));
                            });

                            ifBlock.EmitAssignment(assignAction.TargetExpression, Variable(fieldPointerName));
                        }

                        if (assignAction.NullCheckExpression != null)
                        {
                            body.EmitIfBlock(assignAction.NullCheckExpression,
                                             BuildAssignBlock,
                                             elseBlock =>
                            {
                                elseBlock.EmitAssignment(assignAction.TargetExpression, Null);
                            });
                        }
                        else
                        {
                            BuildAssignBlock(body);
                        }
                    }
                    else
                    {
                        EmitMarshalAction(body, assignAction, assignAction.TargetExpression);
                    }
                }
                else if (action is InvokeAction invokeAction)
                {
                    var paramNames = (invokeAction.Parameters ?? Enumerable.Empty <Action <ExpressionBuilder> >().ToArray());

                    Action <ExpressionBuilder> invokeExpression = null;

                    if (invokeAction.LookupDelegate)
                    {
                        if (invokeAction.DelegateName != null)
                        {
                            body.EmitVariableDeclaration(invokeAction.DelegateName, "commandDelegate", Call(Variable("commandCache"), $"GetCommandDelegate<{invokeAction.DelegateName}>", Literal(invokeAction.MethodName), Literal(invokeAction.LookupScope)));
                        }

                        invokeExpression = DelegateCall(Variable("commandDelegate"), paramNames);
                    }
                    else if (invokeAction.TypeName == null)
                    {
                        invokeExpression = Call(This, invokeAction.MethodName, paramNames);
                    }
                    else
                    {
                        invokeExpression = StaticCall(invokeAction.TypeName, invokeAction.MethodName, paramNames);
                    }

                    if (invokeAction.ReturnName != null)
                    {
                        if (invokeAction.ReturnType != null)
                        {
                            body.EmitVariableDeclaration(invokeAction.ReturnType, invokeAction.ReturnName, invokeExpression);
                        }
                        else
                        {
                            body.EmitAssignment(Variable(invokeAction.ReturnName), invokeExpression);
                        }
                    }
                    else
                    {
                        body.EmitCallExpression(invokeExpression);
                    }
                }
                else if (action is OptionalAction optionalAction)
                {
                    if (optionalAction.ElseActions.Any())
                    {
                        body.EmitIfBlock(optionalAction.CheckExpression,
                                         ifBlock => EmitActions(ifBlock, optionalAction.Actions),
                                         elseBlock => EmitActions(elseBlock, optionalAction.ElseActions));
                    }
                    else
                    {
                        body.EmitIfBlock(optionalAction.CheckExpression,
                                         ifBlock => EmitActions(ifBlock, optionalAction.Actions));
                    }
                }
                else if (action is ValidateAction validationAction)
                {
                    body.EmitIfBlock(StaticCall("SharpVkException", "IsError", Variable(validationAction.VariableName)),
                                     ifBlock =>
                    {
                        ifBlock.EmitThrow(StaticCall("SharpVkException", "Create", Variable(validationAction.VariableName)));
                    });
                }
            }
        }