public static IChelaType DeReferenceType(IChelaType type) { if(!type.IsReference()) return type; ReferenceType refType = (ReferenceType)type; return refType.GetReferencedType(); }
public override AstNode Visit(UsingStatement node) { // Visit the using member. Expression member = node.GetMember(); member.Accept(this); // Cast the pseudo-scope. PseudoScope scope = (PseudoScope)node.GetScope(); // Get the member type. IChelaType memberType = member.GetNodeType(); if (memberType.IsMetaType()) { // Get the actual type. MetaType meta = (MetaType)memberType; memberType = meta.GetActualType(); // Only structure relatives. if (memberType.IsStructure() || memberType.IsClass() || memberType.IsInterface()) { scope.AddAlias(memberType.GetName(), (ScopeMember)memberType); } else { Error(node, "unexpected type."); } } else if (memberType.IsReference()) { // Only static members supported. ScopeMember theMember = (ScopeMember)member.GetNodeValue(); MemberFlags instanceFlags = MemberFlags.InstanceMask & theMember.GetFlags(); if (instanceFlags != MemberFlags.Static) { Error(node, "unexpected member type."); } // Store the member. scope.AddAlias(theMember.GetName(), theMember); } else if (memberType.IsNamespace()) { // Set the namespace chain. Namespace space = (Namespace)member.GetNodeValue(); scope.SetChainNamespace(space); } else { Error(node, "unsupported object to use."); } base.Visit(node); return(node); }
/// <summary> /// Checks for equality with the possibility of ignore some arguments /// and maybe the return type. /// </summary> public bool Equals(FunctionType obj, int ignore, bool noret, bool noflags) { // Reject comparison with null, make sure the lengths are the same. if (obj == null || arguments.Length != obj.arguments.Length || variableArguments != obj.variableArguments) { return(false); } // Compare the return type. if (!noret && returnType != obj.returnType) { return(false); } // Compare the flags. if (!noflags && flags != obj.flags) { return(false); } // Compare the arguments. int size = arguments.Length; for (int i = ignore; i < size; ++i) { IChelaType leftArg = arguments[i]; IChelaType rightArg = obj.arguments[i]; // Handle ref/out equality. if (leftArg != rightArg && leftArg != null && rightArg != null && leftArg.IsReference() && rightArg.IsReference()) { ReferenceType leftRef = (ReferenceType)leftArg; ReferenceType rightRef = (ReferenceType)rightArg; leftArg = leftRef.GetReferencedType(); rightArg = rightRef.GetReferencedType(); } // Reject if different. if (leftArg != rightArg) { return(false); } } // Everything is equal, return true. return(true); }
/// <summary> /// Create the specified array type. /// </summary> public static ArrayType Create(IChelaType valueType, int dimensions, bool readOnly) { // Remove the reference layer. if (valueType.IsReference()) { ReferenceType refType = (ReferenceType)valueType; valueType = refType.GetReferencedType(); } // Don't allow 0 dimensions. if (dimensions == 0) { dimensions = 1; } // Create the array type. ArrayType array = new ArrayType(valueType, dimensions, readOnly); return(arrayTypes.GetOrAdd(array)); }
/// <summary> /// Gets the hash code, but with the possibility of ignoring /// some arguments and the return type.. /// </summary> public int GetHashCode(int ignore, bool noret, bool noflags) { // Add the function type size and variable arguments flag. int hash = arguments.Length ^ variableArguments.GetHashCode(); // Add the return type hash code. if (!noret) { hash ^= RuntimeHelpers.GetHashCode(returnType); } // Add the flags hash code. if (!noflags) { hash ^= flags.GetHashCode(); } // Add the arguments. int size = arguments.Length; for (int i = ignore; i < size; ++i) { // Get the argument. IChelaType arg = arguments[i]; // Handle ref/out equality. if (arg.IsReference()) { ReferenceType refType = (ReferenceType)arg; arg = refType.GetReferencedType(); } // Add the argument hash. hash ^= RuntimeHelpers.GetHashCode(arg); } return(hash); }
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); }
private void RegisterAnonTypeLeaf(IChelaType type, bool registered) { // Make sure lower types are registered. if(!registered) RegisterType(type); if(type.IsReference()) { ReferenceType refType = (ReferenceType)type; RegisterAnonTypeLeaf(refType.GetReferencedType()); } else if(type.IsPointer()) { PointerType pointerType = (PointerType)type; RegisterAnonTypeLeaf(pointerType.GetPointedType()); } else if(type.IsConstant()) { ConstantType constType = (ConstantType)type; RegisterAnonTypeLeaf(constType.GetValueType()); } else if(type.IsArray()) { ArrayType arrayType = (ArrayType)type; RegisterAnonTypeLeaf(arrayType.GetValueType()); } else if(type.IsVector()) { VectorType vectorType = (VectorType)type; RegisterAnonTypeLeaf(vectorType.GetPrimitiveType()); } else if(type.IsMatrix()) { MatrixType matrixType = (MatrixType)type; RegisterAnonTypeLeaf(matrixType.GetPrimitiveType()); } else if(type.IsFunction()) { FunctionType functionType = (FunctionType)type; // Register the return type. RegisterAnonTypeLeaf(functionType.GetReturnType()); // Register the function arguments. for(int i = 0; i < functionType.GetArgumentCount(); ++i) RegisterAnonTypeLeaf(functionType.GetArgument(i)); } else if(type.IsPlaceHolderType()) { // Register the base types. PlaceHolderType placeholder = (PlaceHolderType)type; for(int i = 0; i < placeholder.GetBaseCount(); ++i) RegisterMember(placeholder.GetBase(i)); } else if(type.IsPrimitive()) { // Do nothing. } else if(type.IsTypeInstance()) { StructureInstance instance = (StructureInstance)type; instance.PrepareSerialization(); RegisterMember(instance); } else { // Found a leaf. ScopeMember member = (ScopeMember)type; RegisterMember(member); } }
public IChelaType RefCoerceCounted(AstNode where, IChelaType leftType, IChelaType rightType, object value, out int count) { // Initialize the count. count = 0; // Both types must be references. if(!leftType.IsReference()) return null; if(!rightType.IsReference()) return null; // Remove that reference. IChelaType left = DeReferenceType(leftType); IChelaType right = DeReferenceType(rightType); // Check for primitive coercion. if(left != right) { if(left.IsFirstClass() && right == currentModule.GetAssociatedClass(left)) return leftType; else if(right.IsFirstClass() && left == currentModule.GetAssociatedClass(right)) return leftType; else return null; } return leftType; }
/// <summary> /// Converts T&& into T& /// </summary> private IChelaType SimplifyReference(IChelaType type) { if(type.IsReference()) { ReferenceType refType = (ReferenceType)type; IChelaType referenced = refType.GetReferencedType(); if(referenced.IsReference()) type = referenced; } return type; }
private IChelaType CoerceDeReference(IChelaType type, ref bool isConstant) { if(type.IsReference()) { ReferenceType refType = (ReferenceType)type; IChelaType referencedType = refType.GetReferencedType(); if(referencedType.IsPrimitive() || referencedType.IsStructure() || referencedType.IsReference() || referencedType.IsPointer() || referencedType.IsConstant() || referencedType.IsVector() || referencedType.IsMatrix() || referencedType.IsPlaceHolderType() || referencedType.IsFirstClass()) type = referencedType; // De-const again. isConstant = type.IsConstant(); type = DeConstType(type); } return type; }