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); }
/// <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); }
/// <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); }
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(); }
/// <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); }
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); }
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); } }
public AttributeElement(Span span, TypeRef classref, CallSignature callsignature) : base(span) { this.ClassRef = classref; this.CallSignature = callsignature; }