private void Cast(AstNode where, object original, IChelaType originalType, IChelaType destType, bool isChecked) { // De-const. originalType = DeConstType(originalType); destType = DeConstType(destType); // Don't perform casting if not needed. if(originalType == destType) return; // Dereference. if(original != null && originalType.IsReference() && originalType != ChelaType.GetNullType()) { ReferenceType refType = (ReferenceType) originalType; IChelaType referencedType = refType.GetReferencedType(); bool load = false; if(destType.IsReference() == referencedType.IsReference()) { load = true; } else if(!destType.IsPointer() || referencedType.IsStructure() || referencedType.IsPointer() || referencedType.IsReference() || referencedType.IsVector()) { load = true; } if(load) { ScopeMember member = (ScopeMember) original; if(member.IsVariable()) { Variable variable = (Variable) member; LoadVariableValue(where, variable); } } originalType = DeConstType(referencedType); } if(originalType == destType) return; //bool decrease = destType.GetSize() < originalType.GetSize(); //System.Console.WriteLine("Cast {0} -> {1}", originalType, destType); IChelaType intermediateCast = null; if((originalType.IsInteger() && destType.IsFloatingPoint()) || (originalType.IsFloatingPoint() && destType.IsInteger()) || (originalType.IsFloatingPoint() && destType.IsFloatingPoint()) || (originalType.IsInteger() && destType.IsInteger()) || (destType.IsPointer() && originalType.IsPointer()) ) { builder.CreateCast(destType); } else if((destType == ChelaType.GetSizeType() && originalType.IsPointer()) || (destType.IsPointer() && (originalType == ChelaType.GetSizeType() || originalType == ChelaType.GetPtrDiffType())) ) { Warning(where, "reinterpret_cast is preffered to cast from {0} into {1}", originalType.GetFullName(), destType.GetFullName()); builder.CreateCast(destType); } else if(destType.IsReference() && originalType.IsReference()) { IChelaType rsource = DeReferenceType(originalType); IChelaType rdest = DeReferenceType(originalType); if(rdest != null && rdest.IsStructure()) { if(rsource == null) Error(where, "trying to unbox a null reference."); if(isChecked) builder.CreateChecked(); builder.CreateUnbox(rdest); } else { if(rsource != null && rsource.IsStructure()) builder.CreateBox(rsource); if(isChecked) builder.CreateChecked(); builder.CreateCast(destType); } } else if(destType.IsReference() && originalType.IsFunctionGroup()) { // Cast the delegate type. IChelaType referencedType = DeReferenceType(destType); Class delegateType = (Class)referencedType; // Get the selected function. FunctionGroupSelector selector = (FunctionGroupSelector)original; // Create the delegate. builder.CreateNewDelegate(delegateType, selector.GetSelected()); } else if(destType.IsReference() && originalType.IsStructure()) { builder.CreateBox(originalType); builder.CreateCast(destType); } else if((destType.IsReference() || destType.IsPointer()) && originalType == ChelaType.GetNullType()) { builder.CreateCast(destType); } else if(destType.IsPointer() && originalType.IsStructure()) { // Get the structure type. Structure building = (Structure)originalType; // Building must be IntPtr or UIntPtr. if(building != currentModule.GetAssociatedClass(ChelaType.GetSizeType()) && building != currentModule.GetAssociatedClass(ChelaType.GetPtrDiffType())) Error(where, "cannot perform structure -> pointer cast."); // Unbox the structure. FieldVariable field = (FieldVariable)building.FindMember("__value"); if(field == null) field = (FieldVariable)building.FindMember("m_value"); if(field == null) Error(where, "cannot unbox {0}", building.GetFullName()); builder.CreateExtractPrim(); // Cast into the pointer. builder.CreateCast(destType); } else if(destType.IsStructure() && originalType.IsPointer()) { // Get the structure type. Structure building = (Structure)destType; // Building must be IntPtr or UIntPtr. if(building != currentModule.GetAssociatedClass(ChelaType.GetSizeType()) && building != currentModule.GetAssociatedClass(ChelaType.GetPtrDiffType())) Error(where, "cannot perform pointer -> structure cast."); // Get the structure pointer type. FieldVariable field = (FieldVariable)building.FindMember("__value"); if(field == null) field = (FieldVariable)building.FindMember("m_value"); if(field == null) Error(where, "cannot unbox {0}", building.GetFullName()); // Cast the pointer into the pointer used by the structure. builder.CreateCast(field.GetVariableType()); // Box the pointer. builder.CreatePrimBox(building); } else if(destType.IsStructure() && originalType.IsReference()) { // Don't unbox null. IChelaType rsource = DeReferenceType(originalType); if(rsource == null) Error(where, "trying to unbox a null reference."); if(isChecked) builder.CreateChecked(); builder.CreateUnbox(destType); } else if(destType.IsFirstClass() && originalType.IsStructure()) { // Check dest/source relation. Structure bsource = (Structure)originalType; // TODO: Check the source type its a box. if(!bsource.IsDerivedFrom(currentModule.GetEnumClass()) && currentModule.GetAssociatedClassPrimitive(bsource) == null) Error(where, "structure cannot be casted into a primitive value."); // Get the value field. FieldVariable valueField = (FieldVariable)bsource.FindMember("__value"); if(valueField == null) valueField = (FieldVariable)bsource.FindMember("m_value"); if(valueField == null) Error(where, "invalid enum definition, bug in the compiler."); // Use the intermediate cast. IChelaType boxedType = valueField.GetVariableType(); if(destType != boxedType) intermediateCast = boxedType; // Extract the primitive. builder.CreateExtractPrim(); } else if(destType.IsStructure() && originalType.IsFirstClass()) { // Check dest/source relation. Structure bdest = (Structure)destType; if(!bdest.IsDerivedFrom(currentModule.GetEnumClass()) && currentModule.GetAssociatedClassPrimitive(bdest) == null) Error(where, "primitive value cannot be casted into structure."); // Get the value field. FieldVariable valueField = (FieldVariable)bdest.FindMember("__value"); if(valueField == null) valueField = (FieldVariable)bdest.FindMember("m_value"); if(valueField == null) Error(where, "invalid enum definition, bug in the compiler."); // Perform the intermediate cast. IChelaType enumType = valueField.GetVariableType(); if(originalType != enumType) Cast(where, null, originalType, enumType); // Create the structure. builder.CreatePrimBox(destType); } else if(destType.IsFirstClass() && originalType.IsReference()) { // Get the associated class. Structure assoc = currentModule.GetAssociatedClass(destType); IChelaType rsource = DeReferenceType(originalType); if(rsource == null) Error(where, "trying to unbox null."); if(!rsource.IsStructure() && !rsource.IsClass() && !rsource.IsInterface()) Error(where, "expected class/interface reference."); if(!assoc.IsBasedIn((Structure)rsource)) Error(where, "cannot perform cast " + originalType + " -> " + destType); if(isChecked) builder.CreateChecked(); builder.CreateUnbox(assoc); // Extract the primitive. builder.CreateExtractPrim(); } else if(destType.IsReference() && originalType.IsFirstClass()) { // Get the associated class. Structure assoc = currentModule.GetAssociatedClass(originalType); IChelaType rdest = DeReferenceType(destType); // Make sure the cast is valid. if(!assoc.IsBasedIn((Structure)rdest)) Error(where, "cannot perform cast " + originalType + " -> " + destType); builder.CreateBox(assoc); if(rdest != assoc) builder.CreateCast(destType); } else if(destType.IsStructure() && originalType.IsStructure()) { // Cast the structures. Structure originalBuilding = (Structure)originalType; Structure destBuilding = (Structure)destType; // Only boxed types are supported in this cast. if(originalBuilding.GetSlotCount() != 1 || destBuilding.GetSlotCount() != 1) Error(where, "cannot perform cast structure {0} -> {1}.", originalBuilding.GetFullName(), destBuilding.GetFullName()); // Get the original field. FieldVariable originalField = (FieldVariable)originalBuilding.FindMember("__value"); if(originalField == null) originalField = (FieldVariable)originalBuilding.FindMember("m_value"); // Get the destination field. FieldVariable destField = (FieldVariable)destBuilding.FindMember("__value"); if(destField == null) destField = (FieldVariable)destBuilding.FindMember("m_value"); // Make sure they exist. if(originalField == null || destField == null) Error(where, "cannot perform cast structure {0} -> {1}.", originalBuilding.GetFullName(), destBuilding.GetFullName()); // Unbox the source. Cast(where, original, originalType, originalField.GetVariableType()); // Cast the field. Cast(where, null, originalField.GetVariableType(), destField.GetVariableType()); // Box the casted source. Cast(where, null, destField.GetVariableType(), destType); } else if(destType.IsReference() && originalType.IsPlaceHolderType()) { // TODO: Add type checking. builder.CreateGCast(destType); } else if((destType.IsFirstClass() || destType.IsStructure()) && originalType.IsPlaceHolderType()) { // TODO: Add type checking. builder.CreateGCast(destType); } else if(destType.IsPlaceHolderType() && originalType.IsReference()) { // TODO: Add type checking. builder.CreateGCast(destType); } else if(destType.IsPlaceHolderType() && (originalType.IsFirstClass() || originalType.IsStructure())) { // TODO: Add type checking. builder.CreateGCast(destType); } else Error(where, "cannot perform cast " + originalType + " -> " + destType); // Cast the intermediate type. if(intermediateCast != null) Cast(where, null, intermediateCast, destType); }
public override bool IsInteger() { return(primitiveType.IsInteger()); }