예제 #1
0
        public static IMethod ImplementForwardingCaseFactory(this VirtualType type, string caseName, IMethod caseCtor, IMethod valueTypeCtor)
        {
            var valueType = caseCtor.Parameters.Single().Type;

            Debug.Assert(valueType == valueTypeCtor.DeclaringType);

            var caseFactory = new VirtualMethod(type, Accessibility.Public,
                                                E.SymbolNamer.NameMethod(type, caseName, 0, valueTypeCtor.Parameters, isOverride: false),
                                                valueTypeCtor.Parameters,
                                                returnType: type,
                                                isStatic: true,
                                                doccomment: (valueTypeCtor as IWithDoccomment)?.Doccomment
                                                );

            caseFactory.BodyFactory = () => {
                var call = new IL.NewObj(valueTypeCtor);
                call.Arguments.AddRange(valueTypeCtor.Parameters.Select((p, i) => new IL.LdLoc(new IL.ILVariable(IL.VariableKind.Parameter, p.Type, i))));
                return(EmitExtensions.CreateExpressionFunction(caseFactory,
                                                               new IL.NewObj(caseCtor)
                {
                    Arguments = { call }
                }
                                                               ));
            };
            type.Methods.Add(caseFactory);
            return(caseFactory);
        }
예제 #2
0
        static IMethod ImplementIntoCaseConversion(this VirtualType type, IType valueType, IMethod caseCtor, bool isImplicit = true)
        {
            Debug.Assert(valueType == caseCtor.Parameters.Single().Type);
            Debug.Assert(valueType.Kind != TypeKind.Interface); // can't have conversion from interface
            Debug.Assert(valueType != type);                    // can't have conversion from itself

            var caseFactory = new VirtualMethod(type, Accessibility.Public,
                                                isImplicit ? "op_Implicit" : "op_Explicit",
                                                new[] { new VirtualParameter(valueType, "item") },
                                                returnType: type,
                                                isStatic: true
                                                );

            caseFactory.BodyFactory = () => {
                var @this             = new IL.ILVariable(IL.VariableKind.Parameter, valueType, 0);
                IL.ILInstruction body = new IL.NewObj(caseCtor)
                {
                    Arguments = { new IL.LdLoc(@this) }
                };
                if (valueType.IsReferenceType == true)
                {
                    // pass nulls
                    body = new IL.IfInstruction(
                        new IL.Comp(IL.ComparisonKind.Inequality, Sign.None, new IL.LdLoc(@this), new IL.LdNull()),
                        body,
                        new IL.LdNull()
                        );
                }
                return(EmitExtensions.CreateExpressionFunction(caseFactory, body));
            };
            type.Methods.Add(caseFactory);
            return(caseFactory);
        }
예제 #3
0
        public static IL.ILInstruction CreateTuple(ICompilation compilation, params IL.ILInstruction[] nodes)
        {
            var restTuple = typeof(ValueTuple <, , , , , , ,>);

            Debug.Assert(restTuple.GetGenericArguments().Last().Name == "TRest");
            var maxSize = restTuple.GetGenericArguments().Length;

            if (nodes.Length >= maxSize)
            {
                return(makeTuple(nodes.Take(maxSize - 1).Append(CreateTuple(compilation, nodes.Skip(maxSize - 1).ToArray())).ToArray()));
            }
            else
            {
                return(makeTuple(nodes));
            }

            IL.ILInstruction makeTuple(IL.ILInstruction[] n)
            {
                var t = //n.Length == 0 ? typeof(ValueTuple) :
                        n.Length == 1 ? typeof(ValueTuple <>) :
                        n.Length == 2 ? typeof(ValueTuple <,>) :
                        n.Length == 3 ? typeof(ValueTuple <, ,>) :
                        n.Length == 4 ? typeof(ValueTuple <, , ,>) :
                        n.Length == 5 ? typeof(ValueTuple <, , , ,>) :
                        n.Length == 6 ? typeof(ValueTuple <, , , , ,>) :
                        n.Length == 7 ? typeof(ValueTuple <, , , , , ,>) :
                        n.Length == 8 ? typeof(ValueTuple <, , , , , , ,>) :
                        throw new NotSupportedException($"ValueTuple can not have {n.Length} parameters");
                var tt     = new ParameterizedType(compilation.FindType(t), n.Select(a => a.GetObjectResultType()));
                var ctor   = tt.GetConstructors().Single(c => c.Parameters.Count == n.Length);
                var result = new IL.NewObj(ctor);

                result.Arguments.AddRange(n);
                return(result);
            }
        }