Example #1
0
        private static bool AssertDecodeTypeAndName(
            LNode parentAndName,
            DecoderState state,
            out IType parentType,
            out SimpleName name)
        {
            if (!FeedbackHelpers.AssertArgCount(parentAndName, 2, state.Log))
            {
                parentType = null;
                name       = null;
                return(false);
            }

            parentType = state.DecodeType(parentAndName.Args[0]);

            if (parentType != ErrorType.Instance &&
                state.AssertDecodeSimpleName(parentAndName.Args[1], out name))
            {
                return(true);
            }
            else
            {
                parentType = null;
                name       = null;
                return(false);
            }
        }
 private static NewDelegatePrototype DecodeNewDelegate(IReadOnlyList <LNode> data, DecoderState state)
 {
     return(NewDelegatePrototype.Create(
                state.DecodeType(data[0]),
                state.DecodeMethod(data[1]),
                state.DecodeBoolean(data[2]),
                state.DecodeMethodLookup(data[3])));
 }
Example #3
0
 /// <summary>
 /// Creates a Flame IR field from an appropriately-encoded
 /// LNode.
 /// </summary>
 /// <param name="node">The node to decode.</param>
 /// <param name="decoder">The decoder to use.</param>
 private IrField(LNode node, DecoderState decoder)
     : base(node, decoder)
 {
     this.isStaticCache = new Lazy <bool>(() =>
                                          decoder.DecodeBoolean(node.Args[1]));
     this.fieldTypeCache = new Lazy <IType>(() =>
                                            decoder.DecodeType(node.Args[2]));
 }
 private static IntrinsicPrototype DecodeIntrinsic(IReadOnlyList <LNode> data, DecoderState state)
 {
     // TODO: decode exception specifications.
     return(IntrinsicPrototype.Create(
                FeedbackHelpers.AssertIsId(data[0], state.Log)
             ? data[0].Name.Name
             : "error",
                state.DecodeType(data[1]),
                data[2].Args.EagerSelect <LNode, IType>(state.DecodeType)));
 }
 private static StorePrototype DecodeStore(IReadOnlyList <LNode> data, DecoderState state)
 {
     if (data.Count >= 3)
     {
         return(StorePrototype.Create(
                    state.DecodeType(data[0]),
                    state.DecodeBoolean(data[1]),
                    state.DecodeAlignment(data[2])));
     }
     else if (data.Count >= 2)
     {
         return(StorePrototype.Create(
                    state.DecodeType(data[0]),
                    state.DecodeBoolean(data[1])));
     }
     else
     {
         return(StorePrototype.Create(state.DecodeType(data[0])));
     }
 }
        private static ReinterpretCastPrototype DecodeReinterpretCast(IReadOnlyList <LNode> data, DecoderState state)
        {
            var targetType = state.DecodeType(data[0]);

            if (targetType is PointerType)
            {
                return(ReinterpretCastPrototype.Create((PointerType)targetType));
            }
            else
            {
                state.Log.LogSyntaxError(
                    data[0],
                    new Text("expected a pointer type."));
                return(null);
            }
        }
 private static ConstantPrototype DecodeConstant(IReadOnlyList <LNode> data, DecoderState state)
 {
     return(ConstantPrototype.Create(state.DecodeConstant(data[0]), state.DecodeType(data[1])));
 }
 private static BoxPrototype DecodeBox(IReadOnlyList <LNode> data, DecoderState state)
 {
     return(BoxPrototype.Create(state.DecodeType(data[0])));
 }
 private static SizeOfPrototype DecodeSizeOf(IReadOnlyList <LNode> data, DecoderState state)
 {
     return(SizeOfPrototype.Create(state.DecodeType(data[0]), state.DecodeType(data[1])));
 }
 private static AllocaPrototype DecodeAlloca(IReadOnlyList <LNode> data, DecoderState state)
 {
     return(AllocaPrototype.Create(state.DecodeType(data[0])));
 }
 private static IndirectCallPrototype DecodeIndirectCall(IReadOnlyList <LNode> data, DecoderState state)
 {
     return(IndirectCallPrototype.Create(
                state.DecodeType(data[0]),
                data[1].Args.EagerSelect <LNode, IType>(state.DecodeType)));
 }
 private static StorePrototype DecodeStore(IReadOnlyList <LNode> data, DecoderState state)
 {
     return(StorePrototype.Create(state.DecodeType(data[0])));
 }
 private static LoadPrototype DecodeLoad(IReadOnlyList <LNode> data, DecoderState state)
 {
     return(LoadPrototype.Create(state.DecodeType(data[0])));
 }
Example #14
0
        /// <inheritdoc/>
        public override IType Decode(LNode data, DecoderState state)
        {
            if (data.Calls(pointerSymbol))
            {
                if (!FeedbackHelpers.AssertArgCount(data, 2, state.Log))
                {
                    return(ErrorType.Instance);
                }

                var         elemType = state.DecodeType(data.Args[0]);
                PointerKind kind;
                if (AssertDecodePointerKind(data.Args[1], state, out kind))
                {
                    return(elemType.MakePointerType(kind));
                }
                else
                {
                    return(ErrorType.Instance);
                }
            }
            else if (data.Calls(genericParameterSymbol))
            {
                if (!FeedbackHelpers.AssertArgCount(data, 2, state.Log))
                {
                    return(ErrorType.Instance);
                }

                IGenericMember parent;
                SimpleName     name;

                if (state.AssertDecodeGenericMember(data.Args[0], out parent) &&
                    state.AssertDecodeSimpleName(data.Args[1], out name))
                {
                    var types = state.TypeResolver.ResolveGenericParameters(parent, name);
                    if (AssertSingleChildType(types, data, state, "generic declaration"))
                    {
                        return(types[0]);
                    }
                }
                return(ErrorType.Instance);
            }
            else if (data.Calls(CodeSymbols.Of))
            {
                if (!FeedbackHelpers.AssertMinArgCount(data, 2, state.Log))
                {
                    return(ErrorType.Instance);
                }

                var genericDecl = state.DecodeType(data.Args[0]);
                var genericArgs = data.Args.Slice(1).EagerSelect <LNode, IType>(state.DecodeType);

                int count = genericDecl.GenericParameters.Count;
                if (count != genericArgs.Count)
                {
                    FeedbackHelpers.LogSyntaxError(
                        state.Log,
                        data,
                        FeedbackHelpers.QuoteEven(
                            "type ",
                            FeedbackHelpers.Print(data.Args[0]),
                            " is instantiated with ",
                            genericArgs.Count.ToString(),
                            " arguments but has only ",
                            count.ToString(),
                            " parameters."));
                    return(ErrorType.Instance);
                }

                return(genericDecl.MakeGenericType(genericArgs));
            }
            else if (data.Calls(CodeSymbols.Dot))
            {
                if (!FeedbackHelpers.AssertArgCount(data, 2, state.Log))
                {
                    return(ErrorType.Instance);
                }

                SimpleName childName;
                if (!state.AssertDecodeSimpleName(data.Args[1], out childName))
                {
                    return(ErrorType.Instance);
                }

                var parentType = state.DecodeType(data.Args[0]);
                if (parentType == ErrorType.Instance)
                {
                    // Make sure that we don't log an additional error
                    // just because the parent type was wrong.
                    return(ErrorType.Instance);
                }

                var childTypes = state.TypeResolver.ResolveNestedTypes(parentType, childName);
                if (AssertSingleChildType(childTypes, data, state, "type"))
                {
                    return(childTypes[0]);
                }
                else
                {
                    return(ErrorType.Instance);
                }
            }
            else
            {
                QualifiedName fullName;
                if (state.AssertDecodeQualifiedName(data, out fullName))
                {
                    var types = state.TypeResolver.ResolveTypes(fullName);
                    if (AssertSingleGlobalType(types, data, state))
                    {
                        return(types[0]);
                    }
                    else
                    {
                        return(ErrorType.Instance);
                    }
                }
                else
                {
                    return(ErrorType.Instance);
                }
            }
        }
Example #15
0
        /// <summary>
        /// Decodes an LNode as a constant value.
        /// </summary>
        /// <param name="node">The node to decode.</param>
        /// <param name="state">The decoder state to use.</param>
        /// <returns>A decoded constant.</returns>
        public override Constant Decode(LNode node, DecoderState state)
        {
            // Default-value constants.
            if (node.IsIdNamed(CodeSymbols.Default))
            {
                return(DefaultConstant.Instance);
            }

            // Type/field/method token constants.
            if (node.Calls(CodeSymbols.Typeof, 1))
            {
                return(new TypeTokenConstant(state.DecodeType(node.Args[0])));
            }
            else if (node.Calls(fieldofSymbol, 1))
            {
                return(new FieldTokenConstant(state.DecodeField(node.Args[0])));
            }
            else if (node.Calls(methodofSymbol, 1))
            {
                return(new MethodTokenConstant(state.DecodeMethod(node.Args[0])));
            }

            if (!FeedbackHelpers.AssertIsLiteral(node, state.Log))
            {
                return(null);
            }

            object value;
            Symbol typeMarker;

            // Custom literals.
            if (TryDecomposeCustomLiteral(node, out value, out typeMarker))
            {
                // Arbitrary-width integer literals.
                IntegerSpec spec;
                if (IntegerSpec.TryParse(typeMarker.Name, out spec))
                {
                    BigInteger integerVal;
                    if (BigInteger.TryParse(value.ToString(), out integerVal))
                    {
                        return(new IntegerConstant(integerVal, spec));
                    }
                    else
                    {
                        FeedbackHelpers.LogSyntaxError(
                            state.Log,
                            node,
                            FeedbackHelpers.QuoteEven(
                                "cannot parse ",
                                value.ToString(),
                                " as an integer."));
                        return(null);
                    }
                }
                else
                {
                    FeedbackHelpers.LogSyntaxError(
                        state.Log,
                        node,
                        FeedbackHelpers.QuoteEven(
                            "unknown custom literal type ",
                            typeMarker.Name,
                            "."));
                    return(null);
                }
            }

            value = node.Value;

            // Miscellaneous constants: null, strings, Booleans.
            if (value == null)
            {
                return(NullConstant.Instance);
            }
            else if (value is string)
            {
                return(new StringConstant((string)value));
            }
            else if (value is bool)
            {
                return(BooleanConstant.Create((bool)value));
            }
            // Floating-point numbers.
            else if (value is float)
            {
                return(new Float32Constant((float)value));
            }
            else if (value is double)
            {
                return(new Float64Constant((double)value));
            }
            // Fixed-width integer constants and characters.
            else if (value is char)
            {
                return(new IntegerConstant((char)value));
            }
            else if (value is sbyte)
            {
                return(new IntegerConstant((sbyte)value));
            }
            else if (value is short)
            {
                return(new IntegerConstant((short)value));
            }
            else if (value is int)
            {
                return(new IntegerConstant((int)value));
            }
            else if (value is long)
            {
                return(new IntegerConstant((long)value));
            }
            else if (value is byte)
            {
                return(new IntegerConstant((byte)value));
            }
            else if (value is ushort)
            {
                return(new IntegerConstant((ushort)value));
            }
            else if (value is uint)
            {
                return(new IntegerConstant((uint)value));
            }
            else if (value is ulong)
            {
                return(new IntegerConstant((ulong)value));
            }

            FeedbackHelpers.LogSyntaxError(
                state.Log,
                node,
                new Text("unknown literal type."));
            return(null);
        }
Example #16
0
        /// <inheritdoc/>
        public override ITypeMember Decode(LNode data, DecoderState state)
        {
            if (data.Calls(accessorSymbol))
            {
                if (!FeedbackHelpers.AssertArgCount(data, 2, state.Log) ||
                    !FeedbackHelpers.AssertIsId(data.Args[1], state.Log))
                {
                    return(null);
                }

                var property = state.DecodeProperty(data.Args[0]);
                if (property == null)
                {
                    return(null);
                }
                else
                {
                    var kindName = data.Args[1].Name.Name;
                    var accessor = property.Accessors.FirstOrDefault(
                        acc => accessorKindEncodings[acc.Kind] == kindName);

                    if (accessor == null)
                    {
                        FeedbackHelpers.LogSyntaxError(
                            state.Log,
                            data.Args[1],
                            Quotation.QuoteEvenInBold(
                                "property ",
                                FeedbackHelpers.Print(data.Args[0]),
                                " does not define a ",
                                kindName,
                                " accessor."));
                    }
                    return(accessor);
                }
            }
            else if (data.Calls(CodeSymbols.Dot))
            {
                // Simple dot indicates a field.
                IType      parentType;
                SimpleName name;
                if (!AssertDecodeTypeAndName(data, state, out parentType, out name))
                {
                    return(null);
                }

                var candidates = state.TypeMemberIndex
                                 .GetAll(parentType, name)
                                 .OfType <IField>()
                                 .ToArray();

                return(CheckSingleCandidate(
                           candidates,
                           data.Args[0],
                           data.Args[1],
                           "field",
                           state));
            }
            else if (data.CallsMin(CodeSymbols.IndexBracks, 1))
            {
                IType      parentType;
                SimpleName name;
                if (!AssertDecodeTypeAndName(data.Args[0], state, out parentType, out name))
                {
                    return(null);
                }

                var indexTypes = data.Args
                                 .Slice(1)
                                 .EagerSelect(state.DecodeType);

                var candidates = state.TypeMemberIndex
                                 .GetAll(parentType, name)
                                 .OfType <IProperty>()
                                 .Where(prop =>
                                        prop.IndexerParameters
                                        .Select(p => p.Type)
                                        .SequenceEqual(indexTypes))
                                 .ToArray();

                return(CheckSingleCandidate(
                           candidates,
                           data.Args[0].Args[0],
                           data,
                           "property",
                           state));
            }
            else if (data.Calls(CodeSymbols.Lambda))
            {
                IType      parentType;
                SimpleName name;
                if (!FeedbackHelpers.AssertArgCount(data, 2, state.Log) ||
                    !FeedbackHelpers.AssertIsCall(data.Args[0], state.Log) ||
                    !AssertDecodeTypeAndName(data.Args[0].Target, state, out parentType, out name))
                {
                    return(null);
                }

                // TODO: implement generic parameter decoding, use generic
                // parameters in resolution process.

                var paramTypes = data.Args[0].Args
                                 .EagerSelect(state.DecodeType);

                var retType = state.DecodeType(data.Args[1]);

                var candidates = state.TypeMemberIndex
                                 .GetAll(parentType, name)
                                 .OfType <IMethod>()
                                 .Where(method =>
                                        method.Parameters
                                        .Select(p => p.Type)
                                        .SequenceEqual(paramTypes) &&
                                        object.Equals(
                                            method.ReturnParameter.Type,
                                            retType))
                                 .ToArray();

                return(CheckSingleCandidate(
                           candidates,
                           data.Args[0].Target.Args[0],
                           data,
                           "method",
                           state));
            }
            else if (data.Calls(CodeSymbols.Of))
            {
                if (!FeedbackHelpers.AssertMinArgCount(data, 1, state.Log))
                {
                    return(null);
                }

                var func = state.DecodeMethod(data.Args[0]);
                var args = data.Args.Slice(1).EagerSelect(state.DecodeType);

                if (func.GenericParameters.Count == args.Count)
                {
                    return(func.MakeGenericMethod(args));
                }
                else
                {
                    state.Log.LogSyntaxError(
                        data,
                        Quotation.QuoteEvenInBold(
                            "generic arity mismatch; expected ",
                            func.GenericParameters.Count.ToString(),
                            " parameters but got ",
                            args.Count.ToString(),
                            "."));
                    return(null);
                }
            }
            else
            {
                state.Log.LogSyntaxError(
                    data,
                    Quotation.QuoteEvenInBold(
                        "cannot interpret ",
                        FeedbackHelpers.Print(data),
                        " as a type member; expected a call to one of ",
                        accessorSymbol.Name, ", ",
                        CodeSymbols.Dot.Name, ", ",
                        CodeSymbols.IndexBracks.Name, ", ",
                        CodeSymbols.Of.Name, " or ",
                        CodeSymbols.Lambda.Name));
                return(null);
            }
        }