コード例 #1
0
        public static ISignature FromBuiltinSpec([NotNull] BuiltinSpec spec)
        {
            var pis = spec.Method.GetParameters();

            var parts = pis
                        .Skip(spec.Attr.Data == null ? 1 : 2)
                        .Select(ConvertBuiltinParam)
                        .ToArray();

            var returnPart = ConvertBuiltinParam(
                spec.Method.ReturnParameter ??
                throw new InvalidOperationException($"Missing {nameof(spec.Method.ReturnParameter)}"));

            return(new ZBuiltinSignature(
                       spec.MinArgs, spec.MaxArgs,
                       spec.Attr.MinVersion, spec.Attr.MaxVersion,
                       parts,
                       returnPart));

            // helper
            SignaturePart ConvertBuiltinParam(ParameterInfo pi)
            {
                var type = pi.ParameterType;

                if (type == typeof(void))
                {
                    if (spec.CallType == typeof(VoidCall))
                    {
                        return(LiteralPart.From("T"));
                    }

                    var part = SignatureBuilder.Constrained(
                        SignatureBuilder.Identifier("$return"),
                        spec.CallType == typeof(PredCall) ? Constraint.Boolean : Constraint.AnyObject);

                    return(ApplyParamAttributes(part, pi));
                }

                if (ParameterTypeHandler.Handlers.TryGetValue(type, out var handler))
                {
                    return(ConvertWithHandler(handler, pi));
                }

                // ReSharper disable once PatternAlwaysOfType
                if (type.IsArray && type.GetElementType() is Type t &&
                    ParameterTypeHandler.Handlers.TryGetValue(t, out handler))
                {
                    var part = ConvertWithHandler(handler, pi);
                    return(SignatureBuilder.VarArgs(part, false));
                }

                throw new InvalidOperationException("Unexpected builtin param type");
            }
        }
コード例 #2
0
        static SignaturePart ConvertForSubr(
            [NotNull] Type paramType,
            [NotNull] string name,
            // ReSharper disable once SuggestBaseTypeForParameter
            [NotNull][ItemNotNull] object[] attrs,
            bool isOptional,
            // ReSharper disable once UnusedParameter.Local
            object defaultValue)
        {
            // [Either], [Required], and [Decl] go on the parameter
            var isRequired = attrs.OfType <RequiredAttribute>().Any();

            if (isRequired && isOptional)
            {
                throw new InvalidOperationException("A parameter can't be both required and optional");
            }

            var eitherAttr = attrs.OfType <EitherAttribute>().SingleOrDefault();
            var declAttr   = attrs.OfType <DeclAttribute>().SingleOrDefault();

            // [ZilStructuredParam] and [ZilSequenceParam] go on the element type
            var(isArray, elementType) = CheckArray(paramType);
            var structAttr = elementType.GetCustomAttribute <ZilStructuredParamAttribute>(false);
            var seqAttr    = elementType.GetCustomAttribute <ZilSequenceParamAttribute>(false);

            int attrCount =
                (eitherAttr != null ? 1 : 0) +
                (declAttr != null ? 1 : 0) +
                (structAttr != null ? 1 : 0) +
                (seqAttr != null ? 1 : 0);

            if (attrCount > 1)
            {
                throw new InvalidOperationException(
                          nameof(EitherAttribute) + ", " +
                          nameof(DeclAttribute) + ", " +
                          nameof(ZilStructuredParamAttribute) + ", or " +
                          nameof(ZilSequenceParamAttribute) + ": pick at most one");
            }

            SignaturePart elemPart = null;

            if (eitherAttr != null)
            {
                elemPart = ConvertEither(eitherAttr.Types, eitherAttr.DefaultParamDesc ?? name);
            }
            else if (declAttr != null)
            {
                elemPart = SignatureBuilder.MaybeConvertDecl(declAttr);
            }
            else if (structAttr != null)
            {
                elemPart = ConvertStruct(elementType, structAttr, name);
            }
            else if (seqAttr != null)
            {
                elemPart = ConvertSequence(elementType, name);
            }

            if (elemPart == null)
            {
                elemPart = SignatureBuilder.Identifier(name);

                if (elementType != typeof(ZilObject))
                {
                    elemPart = ConstrainByType(elemPart, elementType);
                }
            }

            if (isArray)
            {
                elemPart = SignatureBuilder.VarArgs(elemPart, isRequired);
            }

            if (isOptional)
            {
                //XXX use defaultValue somehow?
                elemPart = SignatureBuilder.Optional(elemPart);
            }

            return(elemPart);
        }