private IEnumerable <CCodeUnit> BuildUnit(ITypeSymbol type, IAssembliesInfoResolver assembliesInfoResolver) { var unit = new CCodeUnit(type); var isNotModule = type.Name != "<Module>"; var isNotInterfaceOrModule = isNotModule && type.TypeKind != TypeKind.Interface; var methodSymbols = type.GetMembers().OfType <IMethodSymbol>().ToList(); var hasStaticConstructor = methodSymbols.Any(m => m.MethodKind == MethodKind.StaticConstructor); foreach (var field in type.GetMembers().OfType <IFieldSymbol>()) { this.BuildField(field, unit, hasStaticConstructor); } foreach (var @event in type.GetMembers().OfType <IEventSymbol>()) { this.BuildField(new FieldImpl(@event), unit, hasStaticConstructor); } if (hasStaticConstructor) { BuildStaticConstructorVariables(type, unit); } if (isNotModule) { ////BuildTypeHolderVariables(type, unit); BuildTypeDescriptorVariables(type, unit); } var constructors = methodSymbols.Where(m => m.MethodKind == MethodKind.Constructor); foreach (var method in constructors) { this.BuildMethod(method, unit); } var finalizationRequired = type.BaseType != null && type.GetMembers().OfType <IMethodSymbol>().Any(m => m.MethodKind == MethodKind.Destructor); var isAtomicType = type.IsAtomicType(); var namedTypeSymbol = (INamedTypeSymbol)type; if (isNotInterfaceOrModule) { unit.Declarations.Add(new CCodeNewOperatorDeclaration(namedTypeSymbol, finalizationRequired)); unit.Declarations.Add(new CCodeNewOperatorDeclaration(namedTypeSymbol, finalizationRequired, debugVersion: true)); unit.Declarations.Add(new CCodeNewOperatorDeclaration(namedTypeSymbol, finalizationRequired, true)); unit.Declarations.Add(new CCodeNewOperatorDeclaration(namedTypeSymbol, finalizationRequired, true, true)); } if (!isAtomicType && type.TypeKind != TypeKind.Interface) { unit.Declarations.Add(new CCodeGetTypeDescriptorDeclaration(namedTypeSymbol)); } if (type.IsPrimitiveValueType() || type.TypeKind == TypeKind.Enum) { unit.Declarations.Add(new CCodeSpecialTypeOrEnumConstructorDeclaration(namedTypeSymbol, false)); } /* * if (type.IsIntPtrType()) * { * unit.Declarations.Add(new CCodeSpecialTypeOrEnumConstructorDeclaration((INamedTypeSymbol)type, true)); * } */ // to support RuntimeType initialization if (type.IsRuntimeType()) { unit.Declarations.Add(new CCodeRuntimeTypeConstructorDeclaration(namedTypeSymbol, true)); } if (type.IsPrimitiveValueType() || type.TypeKind == TypeKind.Enum || type.IsIntPtrType()) { unit.Declarations.Add(new CCodeCastOperatorDeclaration(namedTypeSymbol)); } if (type.TypeKind == TypeKind.Struct) { unit.Declarations.Add(new CCodeArrowOperatorDeclaration(namedTypeSymbol)); } if (isNotInterfaceOrModule) { // add internal infrustructure unit.Declarations.Add(new CCodeGetTypeVirtualMethodDeclaration(namedTypeSymbol)); unit.Definitions.Add(new CCodeGetTypeVirtualMethodDefinition(namedTypeSymbol)); unit.Declarations.Add(new CCodeIsTypeVirtualMethodDeclaration(namedTypeSymbol)); unit.Definitions.Add(new CCodeIsTypeVirtualMethodDefinition(namedTypeSymbol)); unit.Declarations.Add(new CCodeGetInterfaceVirtualMethodDeclaration(namedTypeSymbol)); unit.Definitions.Add(new CCodeGetInterfaceVirtualMethodDefinition(namedTypeSymbol)); if (!type.IsAbstract) { unit.Declarations.Add(new CCodeCloneVirtualMethod(namedTypeSymbol)); unit.Declarations.Add(new CCodeGetSizeVirtualMethod(namedTypeSymbol)); } if (type.SpecialType == SpecialType.System_Object) { unit.Declarations.Add(new CCodeHashVirtualMethod(namedTypeSymbol)); unit.Declarations.Add(new CCodeEqualsVirtualMethod(namedTypeSymbol)); } } if (type.TypeKind == TypeKind.Interface) { unit.Declarations.Add(new CCodeObjectCastOperatorDeclaration(namedTypeSymbol)); } if (type.SpecialType == SpecialType.System_Array) { unit.Declarations.Add(new CCodeNewOperatorPointerDeclaration(namedTypeSymbol)); unit.Declarations.Add(new CCodeGetArrayElementSizeVirtualMethod(namedTypeSymbol)); unit.Declarations.Add(new CCodeIsPrimitiveTypeArrayVirtualMethod(namedTypeSymbol)); } if (type.TypeKind == TypeKind.Interface) { // add all methods from all interfaces foreach (var method in type.EnumerateInterfaceMethods()) { unit.Declarations.Add(new CCodeMethodDeclaration(type, method)); } } foreach (var method in methodSymbols.Where(m => m.MethodKind != MethodKind.Constructor)) { this.BuildMethod(method, unit); } if (isNotModule) { BuildMethodTableVariables(type, unit); ////BuildRuntimeInfoVariables(type, unit); } if (isNotInterfaceOrModule) { // append interface calls foreach (var interfaceMethod in type.EnumerateInterfaceMethods()) { var method = interfaceMethod; var implementationForInterfaceMember = type.FindImplementationForInterfaceMember(interfaceMethod) as IMethodSymbol; if (implementationForInterfaceMember != null && implementationForInterfaceMember.ExplicitInterfaceImplementations.Any(ei => ei.Equals(method))) { continue; } Debug.Assert(implementationForInterfaceMember != null, "Method for interface can't be found"); unit.Declarations.Add(new CCodeInterfaceMethodAdapterDeclaration(type, interfaceMethod, implementationForInterfaceMember)); unit.Definitions.Add(new CCodeInterfaceMethodAdapterDefinition(type, interfaceMethod, implementationForInterfaceMember)); } } yield return(unit); if (!isNotModule) { yield break; } // return type holder class var typeHolderType = (TypeImpl)TypeImpl.Wrap(type); if (!type.IsAnonymousType()) { typeHolderType.Name = typeHolderType.Name + "__type"; typeHolderType.MetadataName = typeHolderType.MetadataName + "__type"; } else { var namedType = (INamedTypeSymbol)type; typeHolderType.Name = namedType.GetAnonymousTypeName() + "__type"; typeHolderType.MetadataName = namedType.GetAnonymousTypeName() + "__type"; } typeHolderType.BaseType = null; typeHolderType.TypeKind = TypeKind.Struct; typeHolderType.Interfaces = ImmutableArray <INamedTypeSymbol> .Empty; typeHolderType.AllInterfaces = ImmutableArray <INamedTypeSymbol> .Empty; typeHolderType.SpecialType = SpecialType.None; var unitTypeHolder = new CCodeUnit(typeHolderType); BuildTypeHolderVariables(typeHolderType, unitTypeHolder); ////BuildMethodTableVariables(typeHolderType, unitTypeHolder); BuildRuntimeInfoVariables(typeHolderType, type, unitTypeHolder); yield return(unitTypeHolder); }
private IEnumerable <CCodeUnit> BuildUnit(ITypeSymbol type, IAssembliesInfoResolver assembliesInfoResolver) { var namedTypeSymbol = (INamedTypeSymbol)type; var unit = new CCodeUnit(type); var isNotModule = type.Name != "<Module>"; // Class var isNotInterfaceOrModule = isNotModule && type.TypeKind != TypeKind.Interface; var methodSymbols = type.GetMembers().OfType <IMethodSymbol>().ToList(); var hasStaticConstructor = methodSymbols.Any(m => m.MethodKind == MethodKind.StaticConstructor); // to support generic virtual methods #region Virtual Generic methods support var methodsTableType = "__methods_table".ToType(); foreach (var typeParameter in namedTypeSymbol.GetTemplateParameters().Where(t => t.HasConstructorConstraint)) { this.BuildField(new FieldImpl { Type = methodsTableType, Name = "construct_" + typeParameter.Name }, unit, false); } #endregion foreach (var field in type.GetMembers().OfType <IFieldSymbol>()) { this.BuildField(field, unit, hasStaticConstructor); } foreach (var @event in type.GetMembers().OfType <IEventSymbol>()) { this.BuildField(new FieldImpl(@event), unit, hasStaticConstructor); } if (hasStaticConstructor) { BuildStaticConstructorVariables(type, unit); } if (isNotModule) { ////BuildTypeHolderVariables(type, unit); BuildTypeDescriptorVariables(type, unit); } var constructors = methodSymbols.Where(m => m.MethodKind == MethodKind.Constructor); foreach (var method in constructors) { this.BuildMethod(method, unit); } var finalizationRequired = type.BaseType != null && type.GetMembers().OfType <IMethodSymbol>().Any(m => m.MethodKind == MethodKind.Destructor); var isAtomicType = type.IsAtomicType(); if (isNotInterfaceOrModule && !type.IsAbstract) { unit.Declarations.Add(new CCodeNewOperatorDeclaration(namedTypeSymbol, finalizationRequired)); unit.Declarations.Add(new CCodeNewOperatorDeclaration(namedTypeSymbol, finalizationRequired, debugVersion: true)); unit.Declarations.Add(new CCodeNewOperatorDeclaration(namedTypeSymbol, finalizationRequired, true)); unit.Declarations.Add(new CCodeNewOperatorDeclaration(namedTypeSymbol, finalizationRequired, true, true)); } if (!isAtomicType && type.TypeKind != TypeKind.Interface) { unit.Declarations.Add(new CCodeGetTypeDescriptorDeclaration(namedTypeSymbol)); } if (type.IsPrimitiveValueType() || type.TypeKind == TypeKind.Enum) { unit.Declarations.Add(new CCodeSpecialTypeOrEnumConstructorDeclaration(namedTypeSymbol, false)); } /* * if (type.IsIntPtrType()) * { * unit.Declarations.Add(new CCodeSpecialTypeOrEnumConstructorDeclaration((INamedTypeSymbol)type, true)); * } */ // to support RuntimeType initialization if (type.IsRuntimeType()) { unit.Declarations.Add(new CCodeRuntimeTypeConstructorDeclaration(namedTypeSymbol, true)); } if (type.IsPrimitiveValueType() || type.TypeKind == TypeKind.Enum || type.IsIntPtrType()) { unit.Declarations.Add(new CCodeCastOperatorDeclaration(namedTypeSymbol)); } if (type.TypeKind == TypeKind.Struct) { unit.Declarations.Add(new CCodeArrowOperatorDeclaration(namedTypeSymbol)); } if (isNotInterfaceOrModule) { // add internal infrustructure unit.Declarations.Add(new CCodeGetTypeVirtualMethodDeclaration(namedTypeSymbol)); unit.Definitions.Add(new CCodeGetTypeVirtualMethodDefinition(namedTypeSymbol)); unit.Declarations.Add(new CCodeIsTypeVirtualMethodDeclaration(namedTypeSymbol)); unit.Definitions.Add(new CCodeIsTypeVirtualMethodDefinition(namedTypeSymbol)); unit.Declarations.Add(new CCodeGetInterfaceVirtualMethodDeclaration(namedTypeSymbol)); unit.Definitions.Add(new CCodeGetInterfaceVirtualMethodDefinition(namedTypeSymbol)); if (!type.IsAbstract) { unit.Declarations.Add(new CCodeCloneVirtualMethod(namedTypeSymbol)); unit.Declarations.Add(new CCodeGetSizeVirtualMethod(namedTypeSymbol)); } if (type.SpecialType == SpecialType.System_Object) { unit.Declarations.Add(new CCodeHashVirtualMethod(namedTypeSymbol)); unit.Declarations.Add(new CCodeEqualsVirtualMethod(namedTypeSymbol)); } } if (type.TypeKind == TypeKind.Interface) { unit.Declarations.Add(new CCodeObjectCastOperatorDeclaration(namedTypeSymbol)); } if (type.SpecialType == SpecialType.System_Array) { unit.Declarations.Add(new CCodeNewOperatorPointerDeclaration(namedTypeSymbol)); unit.Declarations.Add(new CCodeGetArrayElementSizeVirtualMethod(namedTypeSymbol)); unit.Declarations.Add(new CCodeIsPrimitiveTypeArrayVirtualMethod(namedTypeSymbol)); } if (type.TypeKind == TypeKind.Interface) { // add all methods from all interfaces foreach (var method in type.EnumerateInterfaceMethods()) { unit.Declarations.Add(new CCodeMethodDeclaration(type, method)); } } foreach (var method in methodSymbols.Where(m => m.MethodKind != MethodKind.Constructor)) { this.BuildMethod(method, unit); } // write interface wrappers foreach (var iface in namedTypeSymbol.Interfaces) { unit.Declarations.Add(new CCodeClassDeclaration(new CCodeInterfaceWrapperClass(namedTypeSymbol, iface))); unit.Declarations.Add(new CCodeInterfaceCastOperatorDeclaration(namedTypeSymbol, iface)); } if (isNotModule) { BuildMethodTableVariables(type, unit); ////BuildRuntimeInfoVariables(type, unit); } // transition all methods which have body into source file foreach (var declaration in unit.Declarations.OfType <CCodeMethodDeclaration>().Where(m => m.MethodBodyOpt != null)) { declaration.ToDefinition(unit.Definitions, namedTypeSymbol); } yield return(unit); // TypeHolder if (!isNotModule) { yield break; } // return type holder class var typeHolderType = (TypeImpl)TypeImpl.Wrap(type); if (!type.IsAnonymousType()) { typeHolderType.Name = typeHolderType.Name + "__type"; typeHolderType.MetadataName = typeHolderType.MetadataName + "__type"; } else { var namedType = (INamedTypeSymbol)type; typeHolderType.Name = namedType.GetAnonymousTypeName() + "__type"; typeHolderType.MetadataName = namedType.GetAnonymousTypeName() + "__type"; } typeHolderType.BaseType = null; typeHolderType.TypeKind = TypeKind.Struct; typeHolderType.Interfaces = ImmutableArray <INamedTypeSymbol> .Empty; typeHolderType.AllInterfaces = ImmutableArray <INamedTypeSymbol> .Empty; typeHolderType.SpecialType = SpecialType.None; var unitTypeHolder = new CCodeUnit(typeHolderType); BuildTypeHolderVariables(typeHolderType, unitTypeHolder); ////BuildMethodTableVariables(typeHolderType, unitTypeHolder); BuildRuntimeInfoVariables(typeHolderType, type, unitTypeHolder); yield return(unitTypeHolder); }