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);
            }
        }
Exemple #2
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);
            }
        }