public override AstNode Visit(MemberAccess node) { // This is the same as VariableReference implementation. // Get the node type. IChelaType variableType = node.GetNodeType(); // Ignore type references, namespaces and functions. if (variableType.IsMetaType() || variableType.IsNamespace() || variableType.IsFunctionGroup() || variableType.IsFunction()) { return(node); } // The type must be a reference. variableType = DeReferenceType(variableType); // Now, it must be a constant. if (!variableType.IsConstant()) { Error(node, "constant initialization can't reference no constant variables."); } // The node value, must be the constant variable. FieldVariable constantVar = (FieldVariable)node.GetNodeValue(); // Find the corresponding constant data. ConstantData depData; if (constants.TryGetValue(constantVar, out depData)) { currentConstant.AddDependency(depData); } return(node); }
public override AstNode Visit(FieldDeclaration node) { // Get the field. FieldVariable field = (FieldVariable)node.GetVariable(); // Get the field type. IChelaType fieldType = field.GetVariableType(); if (!fieldType.IsConstant() || field.IsExternal()) { return(node); // Ignore not constant fields. } // Get the initializer. Expression initializer = node.GetDefaultValue(); if (initializer == null) { Error(node, "constants must have initializers."); } // Don't allow multiple definitions. if (constants.ContainsKey(field)) { Error(node, "multiples definitions of a constant."); } // Store the constant. ConstantData data = new ConstantData(field, initializer); this.constants.Add(field, data); // Return the node. return(node); }
public static IChelaType DeConstType(IChelaType type) { if(type == null || !type.IsConstant()) return type; ConstantType constantType = (ConstantType)type; return constantType.GetValueType(); }
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); } }
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; }
public IChelaType CoerceCounted(AstNode where, IChelaType leftType, IChelaType rightType, object value, out int count) { // Initialize the output to zero. count = 0; // Remove constant. bool leftConstant = leftType.IsConstant(); leftType = DeConstType(leftType); bool rightConstant = rightType.IsConstant(); rightType = DeConstType(rightType); // Compute the result for constants. bool resultConstant = leftConstant && rightConstant; // Handle null type. if(leftType == ChelaType.GetNullType()) { leftType = rightType; } else if(rightType == ChelaType.GetNullType()) { rightType = leftType; } // Remove double references leftType = SimplifyReference(leftType); rightType = SimplifyReference(rightType); // Dereference. leftType = CoerceDeReference(leftType, ref leftConstant); rightType = CoerceDeReference(rightType, ref rightConstant); resultConstant = leftConstant && rightConstant; // If the right type is an integer constant, use his actual type. ConstantValue rightValue = value as ConstantValue; if(rightConstant && rightType.IsInteger() && rightValue != null && rightType != ChelaType.GetBoolType() && rightType != ChelaType.GetCharType()) { bool positive = rightValue.IsPositive(); if(leftType.IsUnsigned() && positive) { ulong cval = rightValue.GetULongValue(); if(cval <= 0xFF) rightType = ChelaType.GetByteType(); else if(cval <= 0xFFFF) rightType = ChelaType.GetUShortType(); else if(cval <= 0xFFFFFFFFu) rightType = ChelaType.GetUIntType(); else rightType = ChelaType.GetULongType(); } else if(!positive) { long cval = rightValue.GetLongValue(); // Test using the absolute value. if(cval < 0) cval = -cval; if(cval <= 0x7F) rightType = ChelaType.GetSByteType(); else if(cval <= 0x7FFF) rightType = ChelaType.GetShortType(); else if(cval <= 0x7FFFFFFF) rightType = ChelaType.GetIntType(); else rightType = ChelaType.GetLongType(); } } /*if(currentFunction != null && currentFunction.GetName() == "GetEnumerator") { IChelaType left = DeReferenceType(leftType); IChelaType right = DeReferenceType(rightType); Console.WriteLine("{0}", currentFunction.GetFullName()); Console.WriteLine("left {0} -> {1}", leftType.GetFullName(), left.GetFullName()); Console.WriteLine("right {0} -> {1}", rightType.GetFullName() ,right.GetFullName()); Console.WriteLine("left == right: {0}", left == right); }*/ //System.Console.WriteLine("coerce {0} <-> {1}, eq {2}", leftType, rightType, leftType == rightType); // Any pointer can be casted implicitly into a void* or const void*. if(leftType == ChelaType.GetConstVoidPtrType() && rightType.IsPointer()) { count++; return CoerceConstantResult(ChelaType.GetConstVoidPtrType(), resultConstant); } else if(leftType == ChelaType.GetVoidPtrType() && rightType.IsPointer()) { count++; return CoerceConstantResult(ChelaType.GetVoidPtrType(), resultConstant); } if(rightType == ChelaType.GetConstVoidPtrType() && leftType.IsPointer()) { count++; return CoerceConstantResult(ChelaType.GetConstVoidPtrType(), resultConstant); } else if(rightType == ChelaType.GetVoidPtrType() && leftType.IsPointer()) { count++; return CoerceConstantResult(ChelaType.GetVoidPtrType(), resultConstant); } // Void has special treatment. if(leftType == ChelaType.GetVoidType() || rightType == ChelaType.GetVoidType()) return null; // Invalid coercion. IChelaType destType = leftType; if(leftType != rightType) { // Increase the coercion count. count++; // Vector type checks. bool vector = leftType.IsVector() || rightType.IsVector(); int numcomponents = 1; // Vector->Vector coercion rules. if(leftType.IsVector() && rightType.IsVector()) { // Use primitive coercion rules. vector = false; // Check left vector. VectorType leftVector = (VectorType)leftType; leftType = leftVector.GetPrimitiveType(); numcomponents = leftVector.GetNumComponents(); // Check right vector VectorType rightVector = (VectorType)rightType; rightType = rightVector.GetPrimitiveType(); if(numcomponents != rightVector.GetNumComponents()) return null; } else if(vector) { // Primitive <-> vector coercion is not allowed. if(leftType.IsPrimitive() || rightType.IsPrimitive()) return null; // Not coercion allowed. } // Coerce the types. uint size = Math.Max(leftType.GetSize(), rightType.GetSize()); bool sameSize = (leftType.GetSize() == size) && (rightType.GetSize() == size); bool integer = false; bool floating = false; bool reference = false; bool pointer = false; bool structure = false; bool functionGroup = false; bool firstClass = false; bool placeholder = false; if(leftType.IsInteger()) integer = true; else if(leftType.IsFloatingPoint()) floating = true; else if(leftType.IsReference()) reference = true; else if(leftType.IsPointer()) pointer = true; else if(leftType.IsFunctionGroup()) functionGroup = true; if(leftType.IsPlaceHolderType()) placeholder = true; if(leftType.IsStructure()) structure = true; if(leftType.IsFirstClass()) firstClass = true; if(rightType.IsInteger()) integer = true; else if(rightType.IsFloatingPoint()) floating = true; else if(rightType.IsReference()) reference = true; else if(rightType.IsPointer()) pointer = true; else if(rightType.IsFunctionGroup()) functionGroup = true; if(rightType.IsPlaceHolderType()) placeholder = true; if(rightType.IsStructure()) structure = true; if(rightType.IsFirstClass()) firstClass = true; if(reference && !pointer && !firstClass && !placeholder) { if(leftType.IsReference() && rightType.IsReference()) { // Dereference them. IChelaType left = DeReferenceType(leftType); IChelaType right = DeReferenceType(rightType); IChelaType objectType = currentModule.TypeMap(ChelaType.GetObjectType()); destType = null; //System.Console.WriteLine("[{0}]{1} {2} {3}", leftType, left, right, objectType); if(left == right) { destType = leftType; } else if(left == objectType || right == objectType) { destType = ReferenceType.Create(objectType); } else if(left.IsInterface() || right.IsInterface()) { destType = null; Structure leftBuilding = (Structure)left; Structure rightBuilding = (Structure)right; // TODO: Check this. if(leftBuilding.IsInterface()) { if(rightBuilding.Implements(leftBuilding)) destType = leftType; } if(rightBuilding.IsInterface() && destType == null) { if(leftBuilding.Implements(rightBuilding)) destType = rightType; } } else if(left.IsClass() && right.IsClass()) { Structure leftBuilding = (Structure)left; Structure rightBuilding = (Structure)right; // Make sure the generic inheritance relations are loaded. FixGenericBases(leftBuilding); FixGenericBases(rightBuilding); //System.Console.WriteLine("Check base"); if(leftBuilding.IsDerivedFrom(rightBuilding)) destType = rightType; else if(rightBuilding.IsDerivedFrom(leftBuilding)) destType = leftType; else destType = null; } else if(left.IsArray() && right.IsArray()) { // Array-array coercion. ArrayType leftArray = (ArrayType)left; ArrayType rightArray = (ArrayType)right; // The dimensions must match. if(leftArray.GetDimensions() != rightArray.GetDimensions()) { destType = null; } else { // Get the element types. IChelaType leftElement = leftArray.GetValueType(); IChelaType rightElement = rightArray.GetValueType(); // Compute the read only flag. bool readOnly = leftArray.IsReadOnly() || rightArray.IsReadOnly(); int dimensions = leftArray.GetDimensions(); // Coerce the element types. if(leftElement == rightElement) { destType = ArrayType.Create(leftElement, dimensions, readOnly); } else { IChelaType coerced = Coerce(where, leftElement, rightElement, null); if(coerced != null) destType = ArrayType.Create(coerced, dimensions, readOnly); } // Add the reference layer. if(destType != null) destType = ReferenceType.Create(destType); } } } else if(functionGroup) { // By default there isn't coercion destType = null; // Function -> Delegate coercion. IChelaType refType = null; FunctionGroupType groupType = null; if(leftType.IsReference()) { refType = leftType; groupType = (FunctionGroupType)rightType; } else { refType = rightType; groupType = (FunctionGroupType)leftType; } // One of the types must be a delegate. IChelaType referencedType = DeReferenceType(refType); if(referencedType.IsClass()) { // If one of the types is a delegate, coerce to it. Class delegateClass = currentModule.GetDelegateClass(); Class delegateType = (Class)referencedType; if(delegateType.IsDerivedFrom(delegateClass)) { // Now, select the correct function. FunctionGroup invokeGroup = (FunctionGroup)delegateType.FindMemberRecursive("Invoke"); FunctionGroupSelector selector = (FunctionGroupSelector)value; FunctionGroup delegatedGroup = selector.GetFunctionGroup(); selector.Select(null); foreach(FunctionGroupName gname in invokeGroup.GetFunctions()) { // Ignore static signatures. Function invokeFunction = gname.GetFunction(); if(invokeFunction.IsStatic()) continue; // Only one invoke per delegate is permitted. List<object> arguments = new List<object> (); FunctionType invokeType = invokeFunction.GetFunctionType(); for(int i = 1; i < invokeType.GetArgumentCount(); ++i) arguments.Add(invokeType.GetArgument(i)); // Pick the function. This performs argument covariance. Function picked = PickFunction(where, delegatedGroup, groupType, null, arguments, true); if(picked != null) { // Make sure the return type is compatible. FunctionType pickedType = picked.GetFunctionType(); IChelaType delegateReturn = invokeType.GetReturnType(); IChelaType pickedReturn = pickedType.GetReturnType(); if(pickedReturn != delegateReturn && Coerce(pickedReturn, delegateReturn) != delegateReturn) Error(where, "incompatible delegate and invoked function return type."); selector.Select(picked); break; } } if(selector.GetSelected() != null) destType = refType; else destType = null; } } } else { // Support structure boxing IChelaType referencedType; IChelaType valueType; if(leftType.IsReference()) { referencedType = DeReferenceType(leftType); valueType = rightType; } else { referencedType = DeReferenceType(rightType); valueType = leftType; } if(valueType.IsStructure()) { Structure referencedClass = referencedType as Structure; Structure building = (Structure)valueType; if(referencedClass != null && building.IsBasedIn(referencedClass)) destType = ReferenceType.Create(referencedType); else destType = null; } else { destType = null; } } } else if(pointer && !reference && !firstClass && !placeholder) { if(leftType.IsPointer() && rightType.IsPointer()) { // Depointer them. IChelaType left = DePointerType(leftType); IChelaType right = DePointerType(rightType); // De-const. bool pointerToConstant = false; if(left.IsConstant() || right.IsConstant()) pointerToConstant = true; left = DeConstType(left); right = DeConstType(right); if(left == right) { destType = left; } else if(left.IsStructure() && right.IsStructure()) { Structure leftBuilding = (Structure)left; Structure rightBuilding = (Structure)right; if(leftBuilding.IsDerivedFrom(rightBuilding)) destType = right; else if(rightBuilding.IsDerivedFrom(leftBuilding)) destType = left; else destType = null; } else if(left.IsStructure() && right.IsFirstClass() || right.IsStructure() && left.IsFirstClass()) { // They could represent the same type. Structure building; IChelaType primitive; if(left.IsStructure()) { building = (Structure)left; primitive = right; } else { building = (Structure)right; primitive = left; } // Get the primitive associated class. Structure associated = currentModule.GetAssociatedClass(primitive); // If the structure is the associated class, they are the same type. if(building == associated) destType = left; else destType = null; } else { destType = null; } // Make the pointer. if(destType != null) { if(pointerToConstant) destType = PointerType.Create(ConstantType.Create(destType)); else destType = PointerType.Create(destType); } } else { // Invalid coercion. destType = null; } } else if(firstClass && reference) { // Select the primitive and reference type. IChelaType primType; IChelaType refType; if(leftType.IsFirstClass()) { primType = leftType; refType = rightType; } else { primType = rightType; refType = leftType; } // Get the referenced type. Structure assoc = currentModule.GetAssociatedClass(primType); IChelaType referencedType = DeReferenceType(refType); if(assoc == null || (!referencedType.IsClass() && !referencedType.IsStructure() && !referencedType.IsInterface())) return null; Structure building = (Structure)referencedType; // Only cast if there are related. if(assoc.IsBasedIn(building)) destType = refType; else destType = null; } else if(firstClass && structure) { IChelaType primType; IChelaType structType; if(leftType.IsFirstClass()) { primType = leftType; structType = rightType; } else { primType = rightType; structType = leftType; } // Get the associated type Structure building = (Structure)structType; Structure assoc = currentModule.GetAssociatedClass(primType); if(assoc == null || structType != assoc) { destType = null; // Get the value field. FieldVariable valueField = (FieldVariable)building.FindMember("__value"); if(valueField == null) valueField = (FieldVariable)building.FindMember("m_value"); // Check enumerations if(valueField != null) { IChelaType valueType = valueField.GetVariableType(); Class enumClass = currentModule.GetEnumClass(); if(building.IsDerivedFrom(enumClass)) { if(primType == valueType) destType = primType; } else { // Generic structure. IChelaType coerced = Coerce(valueType, primType); if(coerced == valueType) destType = structType; else destType = coerced; } } } else { // Don't count coercion count = 0; destType = leftType; } } else if(placeholder && reference) { // Check for placeholder->object or constraint. PlaceHolderType placeholderType = null; IChelaType referenceType = null; if(leftType.IsPlaceHolderType()) { placeholderType = (PlaceHolderType)leftType; referenceType = rightType; } else { placeholderType = (PlaceHolderType)rightType; referenceType = leftType; } // Get the referenced type. IChelaType referencedType = DeReferenceType(referenceType); // Default result. destType = null; // Use the constraints. if(referencedType.IsInterface() || referencedType.IsClass()) { Structure building = (Structure)referencedType; // Check if one constraint implements building. bool compatible = false; // Object is implicit. if(building == currentModule.GetObjectClass()) compatible = true; // Value types are deriverd from the ValueType class. else if(placeholderType.IsValueType() && building == currentModule.GetValueTypeClass()) compatible = true; for(int i = 0; i < placeholderType.GetBaseCount() && !compatible; ++i) { Structure baseBuilding = (Structure)placeholderType.GetBase(i); if(baseBuilding == building) // The constraint is the building. compatible = true; // The constraint implements the target type. else if(baseBuilding.IsClass() && baseBuilding.IsDerivedFrom(building)) compatible = true; // The constraint implements the interface else if(baseBuilding.IsInterface() && baseBuilding.Implements(building)) compatible = true; // Not implemented by the constraint. } // If the type is compatible, perform coercion. if(compatible) destType = referenceType; } } else if(integer && floating && !placeholder) { // int->(float|double) if(size <= 4) destType = ChelaType.GetFloatType(); else destType = ChelaType.GetDoubleType(); } else if(integer && !placeholder) { // int->long? // Find the signs. bool signed = !leftType.IsUnsigned() || !rightType.IsUnsigned(); bool unsigned = leftType.IsUnsigned() || rightType.IsUnsigned(); bool withSign = signed; // If they have the same size and different signs, increase the size if(sameSize && signed && unsigned) ++size; if(size == 1) { if(withSign) destType = ChelaType.GetSByteType(); else destType = ChelaType.GetByteType(); } else if(size == 2) { if(withSign) destType = ChelaType.GetShortType(); else destType = ChelaType.GetUShortType(); } else if(size <= 4) { if(withSign) destType = ChelaType.GetIntType(); else destType = ChelaType.GetUIntType(); } else if(size == 100) { if(withSign) destType = null; else destType = ChelaType.GetSizeType(); } else if(size <= 8) { if(withSign) destType = ChelaType.GetLongType(); else destType = ChelaType.GetULongType(); } } else if(floating && !placeholder) { // float->double if(size <= 4) destType = ChelaType.GetFloatType(); else destType = ChelaType.GetDoubleType(); } else { // Failed to coerce. destType = null; } // Vector coercion. if(destType != null && numcomponents > 1 && destType.IsPrimitive()) destType = VectorType.Create(destType, numcomponents); } return CoerceConstantResult(destType, resultConstant); }