Beispiel #1
0
        public BoundTypeRef BindTypeRef(AST.TypeRef tref)
        {
            var bound = new BoundTypeRef(tref);

            if (tref is AST.IndirectTypeRef)
            {
                bound.TypeExpression = BindExpression(((AST.IndirectTypeRef)tref).ClassNameVar);
            }

            return(bound);
        }
Beispiel #2
0
        /// <summary>
        /// Binds <see cref="AST.TypeRef"/> to a type symbol.
        /// </summary>
        /// <param name="tref">Type reference.</param>
        /// <param name="selfHint">Optional.
        /// Current type scope for better <paramref name="tref"/> resolution since <paramref name="tref"/> might be ambiguous</param>
        /// <param name="nullable">Whether the resulting type must be able to contain NULL. Default is <c>false</c>.</param>
        /// <returns>Resolved symbol.</returns>
        internal TypeSymbol GetTypeFromTypeRef(AST.TypeRef tref, SourceTypeSymbol selfHint = null, bool nullable = false)
        {
            if (tref == null)
            {
                return(null);
            }

            var t = this.TypeRefFactory.CreateFromTypeRef(tref, null, selfHint);

            var symbol = t.ResolveRuntimeType(this);

            if (t.IsNullable || nullable)
            {
                // TODO: for value types -> Nullable<T>
                symbol = MergeNull(symbol);
            }

            return(symbol);
        }
Beispiel #3
0
        /// <summary>
        /// Binds <see cref="AST.TypeRef"/> to a type symbol.
        /// </summary>
        /// <param name="tref">Type reference.</param>
        /// <param name="selfHint">Optional.
        /// Current type scope for better <paramref name="tref"/> resolution since <paramref name="tref"/> might be ambiguous</param>
        /// <param name="nullable">Whether the resulting type must be able to contain NULL. Default is <c>false</c>.</param>
        /// <param name="phpLang">PHP semantic - specifies how to treat <c>int</c> and <c>string</c> special types.</param>
        /// <returns>Resolved symbol.</returns>
        internal TypeSymbol GetTypeFromTypeRef(AST.TypeRef tref, SourceTypeSymbol selfHint = null, bool nullable = false, bool phpLang = false)
        {
            if (tref == null)
            {
                return(null);
            }

            var t = this.TypeRefFactory.CreateFromTypeRef(tref, self: selfHint, phpLang: phpLang);

            var symbol = t.ResolveRuntimeType(this);

            if (t.IsNullable || nullable)
            {
                // TODO: asSystemNullable: true // to generate strongly typed function signatures
                symbol = MergeNull(symbol, asSystemNullable: false);
            }

            return(symbol);
        }
Beispiel #4
0
        public static ITypeRef CreateTypeRef(AST.TypeRef tref)
        {
            if (tref is AST.PrimitiveTypeRef)
            {
                switch (((AST.PrimitiveTypeRef)tref).PrimitiveTypeName)
                {
                case AST.PrimitiveTypeRef.PrimitiveType.@int: return(TypeRefFactory.LongTypeRef);

                case AST.PrimitiveTypeRef.PrimitiveType.@float: return(TypeRefFactory.DoubleTypeRef);

                case AST.PrimitiveTypeRef.PrimitiveType.@string: return(TypeRefFactory.StringTypeRef);

                case AST.PrimitiveTypeRef.PrimitiveType.@bool: return(TypeRefFactory.BoolTypeRef);

                //case AST.PrimitiveTypeRef.PrimitiveType.array: return TypeRefFactory.ArrayTypeRef;
                //case AST.PrimitiveTypeRef.PrimitiveType.callable: return TypeRefFactory.CallableTypeRef;
                //case AST.PrimitiveTypeRef.PrimitiveType.@void: return 0;
                //case AST.PrimitiveTypeRef.PrimitiveType.iterable: return GetArrayTypeMask() | GetTypeMask(NameUtils.SpecialNames.Traversable, true);   // array | Traversable
                case AST.PrimitiveTypeRef.PrimitiveType.@object: return(TypeRefFactory.CreateTypeRef(NameUtils.SpecialNames.System_Object));
                }
            }
            else if (tref is AST.INamedTypeRef named)
            {
                return(TypeRefFactory.CreateTypeRef(named.ClassName));
            }
            //else if (tref is AST.ReservedTypeRef) return GetTypeMaskOfReservedClassName(((AST.ReservedTypeRef)tref).QualifiedName.Value.Name);
            else if (tref is AST.GenericTypeRef generic)
            {
                return(new GenericClassTypeRef(
                           generic.QualifiedName.Value, // throw if indirect
                           generic.GenericParams.Select(CreateTypeRef).ToImmutableArray()));
            }

            //
            throw new ArgumentException();
        }
Beispiel #5
0
        /// <summary>
        /// Gets type mask corresponding to given TypeRef within this context.
        /// </summary>
        public TypeRefMask GetTypeMask(AST.TypeRef /*!*/ tref, bool includesSubclasses = true)
        {
            Contract.ThrowIfNull(tref);

            if (tref != null)
            {
                if (tref is AST.PrimitiveTypeRef)
                {
                    switch (((AST.PrimitiveTypeRef)tref).PrimitiveTypeName)
                    {
                    case AST.PrimitiveTypeRef.PrimitiveType.@int: return(GetLongTypeMask());

                    case AST.PrimitiveTypeRef.PrimitiveType.@float: return(GetDoubleTypeMask());

                    case AST.PrimitiveTypeRef.PrimitiveType.@string: return(GetStringTypeMask());

                    case AST.PrimitiveTypeRef.PrimitiveType.@bool: return(GetBooleanTypeMask());

                    case AST.PrimitiveTypeRef.PrimitiveType.array: return(GetArrayTypeMask());

                    case AST.PrimitiveTypeRef.PrimitiveType.callable: return(GetCallableTypeMask());

                    case AST.PrimitiveTypeRef.PrimitiveType.@void: return(0);

                    case AST.PrimitiveTypeRef.PrimitiveType.iterable: return(GetArrayTypeMask() | GetTypeMask(NameUtils.SpecialNames.Traversable, true));      // array | Traversable

                    case AST.PrimitiveTypeRef.PrimitiveType.@object: return(GetSystemObjectTypeMask());

                    default: throw new ArgumentException();
                    }
                }
                else if (tref is AST.INamedTypeRef)
                {
                    return(GetTypeMask(((AST.INamedTypeRef)tref).ClassName, includesSubclasses));
                }
                else if (tref is AST.ReservedTypeRef)
                {
                    return(GetTypeMaskOfReservedClassName(((AST.ReservedTypeRef)tref).QualifiedName.Value.Name));
                }
                else if (tref is AST.AnonymousTypeRef)
                {
                    return(GetTypeMask(((AST.AnonymousTypeRef)tref).TypeDeclaration.GetAnonymousTypeQualifiedName(), false));
                }
                else if (tref is AST.MultipleTypeRef)
                {
                    TypeRefMask result = 0;
                    foreach (var x in ((AST.MultipleTypeRef)tref).MultipleTypes)
                    {
                        result |= GetTypeMask(x, includesSubclasses);
                    }
                    return(result);
                }
                else if (tref is AST.NullableTypeRef)
                {
                    return(GetTypeMask(((AST.NullableTypeRef)tref).TargetType) | this.GetNullTypeMask());
                }
                else if (tref is AST.GenericTypeRef)
                {
                    return(GetTypeMask(((AST.GenericTypeRef)tref).TargetType, includesSubclasses));                                  // TODO: now we are ignoring type args
                }
                else if (tref is AST.IndirectTypeRef)
                {
                    return(GetTypeMask((AST.IndirectTypeRef)tref, true));
                }
            }

            return(TypeRefMask.AnyType);
        }
Beispiel #6
0
        public BoundTypeRef CreateFromTypeRef(Ast.TypeRef tref, SemanticsBinder binder = null, SourceTypeSymbol self = null, bool objectTypeInfoSemantic = false)
        {
            if (tref is Ast.PrimitiveTypeRef pt)
            {
                switch (pt.PrimitiveTypeName)
                {
                case Ast.PrimitiveTypeRef.PrimitiveType.@int: return(LongTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.@float: return(DoubleTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.@string: return(StringTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.@bool: return(BoolTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.array: return(ArrayTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.callable: return(CallableTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.@void: return(VoidTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.iterable: return(IterableTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.@object: return(ObjectTypeRef);

                default: throw ExceptionUtilities.UnexpectedValue(pt.PrimitiveTypeName);
                }
            }
            else if (tref is Ast.INamedTypeRef named)
            {
                if (named.ClassName == NameUtils.SpecialNames.System_Object)
                {
                    return(ObjectTypeRef);
                }
                //if (named.ClassName == NameUtils.SpecialNames.stdClass) return StdClassTypeRef;

                if (named is Ast.TranslatedTypeRef tt && self != null && tt.OriginalType is Ast.ReservedTypeRef reserved)
                {
                    // keep self,parent,static not translated - better in cases where the type is ambiguous
                    return(CreateFromTypeRef(reserved, binder, self, objectTypeInfoSemantic));
                }

                return(new BoundClassTypeRef(named.ClassName, binder?.Routine, self ?? binder?.Self));
            }
            else if (tref is Ast.ReservedTypeRef reserved)
            {
                return(new BoundReservedTypeRef(reserved.Type, self));
            }
            else if (tref is Ast.AnonymousTypeRef at)
            {
                return(new BoundTypeRefFromSymbol(at.TypeDeclaration.GetProperty <SourceTypeSymbol>()));
            }
            else if (tref is Ast.MultipleTypeRef mt)
            {
                return(new BoundMultipleTypeRef(Create(mt.MultipleTypes, binder, self)));
            }
            else if (tref is Ast.NullableTypeRef nullable)
            {
                var t = CreateFromTypeRef(nullable.TargetType, binder, self, objectTypeInfoSemantic);
                t.IsNullable = true;
                return(t);
            }
            else if (tref is Ast.GenericTypeRef gt)
            {
                return(new BoundGenericClassTypeRef(
                           CreateFromTypeRef(gt.TargetType, binder, self, objectTypeInfoSemantic),
                           Create(gt.GenericParams, binder, self)));
            }
            else if (tref is Ast.IndirectTypeRef it)
            {
                return(new BoundIndirectTypeRef(
                           binder.BindWholeExpression(it.ClassNameVar, BoundAccess.Read).SingleBoundElement(),
                           objectTypeInfoSemantic));
            }
            else
            {
                throw ExceptionUtilities.UnexpectedValue(tref);
            }
        }
        /// <summary>
        /// Binds <see cref="AST.TypeRef"/> to a type symbol.
        /// </summary>
        /// <param name="tref">Type reference.</param>
        /// <returns>Resolved symbol.</returns>
        internal TypeSymbol GetTypeFromTypeRef(AST.TypeRef tref)
        {
            if (tref != null)
            {
                if (tref is AST.PrimitiveTypeRef)
                {
                    switch (((AST.PrimitiveTypeRef)tref).PrimitiveTypeName)
                    {
                    case AST.PrimitiveTypeRef.PrimitiveType.@int: return(CoreTypes.Long);

                    case AST.PrimitiveTypeRef.PrimitiveType.@float: return(CoreTypes.Double);

                    case AST.PrimitiveTypeRef.PrimitiveType.@string: return(CoreTypes.String);      // TODO: PhpString ?

                    case AST.PrimitiveTypeRef.PrimitiveType.@bool: return(CoreTypes.Boolean);

                    case AST.PrimitiveTypeRef.PrimitiveType.array: return(CoreTypes.PhpArray);

                    case AST.PrimitiveTypeRef.PrimitiveType.callable: return(CoreTypes.PhpValue);    // array|string|object

                    case AST.PrimitiveTypeRef.PrimitiveType.@void: return(CoreTypes.Void);

                    case AST.PrimitiveTypeRef.PrimitiveType.iterable: return(CoreTypes.PhpValue);      // array|Traversable

                    default: throw new ArgumentException();
                    }
                }
                else if (tref is AST.INamedTypeRef)
                {
                    var t = (NamedTypeSymbol)GlobalSemantics.GetType(((AST.INamedTypeRef)tref).ClassName);
                    return(t.IsErrorTypeOrNull()
                        ? CoreTypes.Object.Symbol   // TODO: merge candidates if any
                        : t);
                }
                else if (tref is AST.ReservedTypeRef)
                {
                    throw new ArgumentException();                                   // NOTE: should be translated by parser to AliasedTypeRef
                }
                else if (tref is AST.AnonymousTypeRef)
                {
                    return((NamedTypeSymbol)GlobalSemantics.GetType(((AST.AnonymousTypeRef)tref).TypeDeclaration.GetAnonymousTypeQualifiedName()));
                }
                else if (tref is AST.MultipleTypeRef)
                {
                    TypeSymbol result = null;
                    foreach (var x in ((AST.MultipleTypeRef)tref).MultipleTypes)
                    {
                        var resolved = GetTypeFromTypeRef(x);
                        result = (result != null) ? Merge(result, resolved) : resolved;
                    }
                    return(result);
                }
                else if (tref is AST.NullableTypeRef)
                {
                    MergeNull(GetTypeFromTypeRef(((AST.NullableTypeRef)tref).TargetType));                                   // ?((AST.NullableTypeRef)tref).TargetType
                }
                else if (tref is AST.GenericTypeRef)
                {
                    throw new NotImplementedException();                                  //((AST.GenericTypeRef)tref).TargetType
                }
                else if (tref is AST.IndirectTypeRef)
                {
                    throw new NotImplementedException();
                }
            }

            return(null);
        }
        /// <summary>
        /// Binds <see cref="AST.TypeRef"/> to a type symbol.
        /// </summary>
        /// <param name="tref">Type reference.</param>
        /// <param name="selfHint">Optional.
        /// Current type scope for better <paramref name="tref"/> resolution since <paramref name="tref"/> might be ambiguous</param>
        /// <param name="nullable">Whether the resulting type must be able to contain NULL. Default is <c>false</c>.</param>
        /// <returns>Resolved symbol.</returns>
        internal TypeSymbol GetTypeFromTypeRef(AST.TypeRef tref, SourceTypeSymbol selfHint = null, bool nullable = false)
        {
            if (tref == null)
            {
                return(null);
            }

            if (nullable)
            {
                return(MergeNull(GetTypeFromTypeRef(tref, selfHint, nullable: false))); // TODO: Nullable<T>
            }

            if (tref is AST.PrimitiveTypeRef)
            {
                switch (((AST.PrimitiveTypeRef)tref).PrimitiveTypeName)
                {
                case AST.PrimitiveTypeRef.PrimitiveType.@int: return(CoreTypes.Long);

                case AST.PrimitiveTypeRef.PrimitiveType.@float: return(CoreTypes.Double);

                case AST.PrimitiveTypeRef.PrimitiveType.@string: return(CoreTypes.String);      // TODO: PhpString ?

                case AST.PrimitiveTypeRef.PrimitiveType.@bool: return(CoreTypes.Boolean);

                case AST.PrimitiveTypeRef.PrimitiveType.array: return(CoreTypes.PhpArray);

                case AST.PrimitiveTypeRef.PrimitiveType.callable: return(CoreTypes.PhpValue);    // array|string|object

                case AST.PrimitiveTypeRef.PrimitiveType.@void: return(CoreTypes.Void);

                case AST.PrimitiveTypeRef.PrimitiveType.iterable: return(CoreTypes.PhpValue);   // array|Traversable

                case AST.PrimitiveTypeRef.PrimitiveType.@object: return(CoreTypes.Object);      // Object

                default: throw new ArgumentException();
                }
            }
            else if (tref is AST.INamedTypeRef namedtref)
            {
                if (selfHint != null)
                {
                    if (namedtref.ClassName == selfHint.FullName)
                    {
                        return(selfHint);
                    }
                    if (selfHint.BaseType is IPhpTypeSymbol phpt && namedtref.ClassName == phpt.FullName)
                    {
                        return(selfHint.BaseType);
                    }
                }

                var t = (NamedTypeSymbol)GlobalSemantics.ResolveType(namedtref.ClassName);
                return(t.IsErrorTypeOrNull()
                    ? CoreTypes.Object.Symbol   // TODO: merge candidates if any
                    : t);
            }
            else if (tref is AST.ReservedTypeRef)
            {
                throw new ArgumentException();                                   // NOTE: should be translated by parser to AliasedTypeRef
            }
            else if (tref is AST.AnonymousTypeRef)
            {
                return((NamedTypeSymbol)GlobalSemantics.ResolveType(((AST.AnonymousTypeRef)tref).TypeDeclaration.GetAnonymousTypeQualifiedName()));
            }
            else if (tref is AST.MultipleTypeRef)
            {
                TypeSymbol result = null;
                foreach (var x in ((AST.MultipleTypeRef)tref).MultipleTypes)
                {
                    var resolved = GetTypeFromTypeRef(x, selfHint);
                    result = (result != null) ? Merge(result, resolved) : resolved;
                }
                return(result);
            }
            else if (tref is AST.NullableTypeRef nullableref)
            {
                return(GetTypeFromTypeRef(nullableref.TargetType, selfHint, nullable: true));
            }
            else if (tref is AST.GenericTypeRef)
            {
                throw new NotImplementedException();                                  //((AST.GenericTypeRef)tref).TargetType
            }
            else if (tref is AST.IndirectTypeRef)
            {
                throw new NotImplementedException();
            }

            throw ExceptionUtilities.UnexpectedValue(tref);
        }
Beispiel #9
0
        public BoundTypeRef CreateFromTypeRef(Ast.TypeRef tref, SemanticsBinder binder = null, SourceTypeSymbol self = null, bool objectTypeInfoSemantic = false, int arity = -1, bool phpLang = false)
        {
            if (tref is Ast.PrimitiveTypeRef pt)
            {
                switch (pt.PrimitiveTypeName)
                {
                case Ast.PrimitiveTypeRef.PrimitiveType.@int: return(LongTypeRef);    // CONSIDER: phpLang ? LongTypeRef : Create(Int32);

                case Ast.PrimitiveTypeRef.PrimitiveType.@float: return(DoubleTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.@string: return(phpLang ? WritableStringRef : StringTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.@bool: return(BoolTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.array: return(ArrayTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.callable: return(CallableTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.@void: return(VoidTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.iterable: return(IterableTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.@object: return(ObjectTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.mixed: return(MixedTypeRef);

                case Ast.PrimitiveTypeRef.PrimitiveType.never: return(VoidTypeRef);

                default: throw ExceptionUtilities.UnexpectedValue(pt.PrimitiveTypeName);
                }
            }
            else if (tref is Ast.INamedTypeRef named)
            {
                if (named.ClassName == NameUtils.SpecialNames.System_Object)
                {
                    return(ObjectTypeRef);
                }
                //if (named.ClassName == NameUtils.SpecialNames.stdClass) return StdClassTypeRef;

                if (named is Ast.TranslatedTypeRef tt && self != null && tt.OriginalType is Ast.ReservedTypeRef reserved)
                {
                    // keep self,parent,static not translated - better in cases where the type is ambiguous
                    return(CreateFromTypeRef(reserved, binder, self, objectTypeInfoSemantic, phpLang: phpLang));
                }

                return(new BoundClassTypeRef(named.ClassName, binder?.Routine, self ?? binder?.Self, arity));
            }
            else if (tref is Ast.ReservedTypeRef reserved)
            {
                return(new BoundReservedTypeRef(reserved.Type, self));
            }
            else if (tref is Ast.AnonymousTypeRef at)
            {
                return(new BoundTypeRefFromSymbol(at.TypeDeclaration.GetProperty <SourceTypeSymbol>()));
            }
            else if (tref is Ast.MultipleTypeRef mt)
            {
                return(new BoundMultipleTypeRef(Create(mt.MultipleTypes, binder, self, nullClassSemantic: true, phpLang: phpLang)));
            }
            else if (tref is Ast.NullableTypeRef nullable)
            {
                var t = CreateFromTypeRef(nullable.TargetType, binder, self, objectTypeInfoSemantic, phpLang: phpLang);
                if (t.IsNullable != true)
                {
                    if (t is BoundPrimitiveTypeRef bpt)
                    {
                        // do not change the cached singleton // https://github.com/peachpiecompiler/peachpie/issues/455
                        t = new BoundPrimitiveTypeRef(bpt.TypeCode);
                    }

                    t.IsNullable = true;
                }
                return(t);
            }
            else if (tref is Ast.GenericTypeRef gt)
            {
                return(new BoundGenericClassTypeRef(
                           CreateFromTypeRef(gt.TargetType, binder, self, objectTypeInfoSemantic, arity: gt.GenericParams.Count, phpLang: phpLang),
                           Create(gt.GenericParams, binder, self, phpLang: false)));
            }
            else if (tref is Ast.IndirectTypeRef it)
            {
                return(new BoundIndirectTypeRef(
                           binder.BindWholeExpression(it.ClassNameVar, BoundAccess.Read).SingleBoundElement(),
                           objectTypeInfoSemantic));
            }
            else
            {
                throw ExceptionUtilities.UnexpectedValue(tref);
            }
        }
Beispiel #10
0
 public AttributeElement(Span span, TypeRef classref, CallSignature callsignature)
     : base(span)
 {
     this.ClassRef      = classref;
     this.CallSignature = callsignature;
 }