Пример #1
0
		std::string MethodSetElement::toString() const {
			return makeString("MethodSetElement(constPredicate: %s, noexceptPredicate: %s, requirePredicate: %s, returnType: %s, ...)",
				constPredicate().toString().c_str(),
				noexceptPredicate().toString().c_str(),
				requirePredicate().toString().c_str(),
				returnType()->toString().c_str());
		}
Пример #2
0
		bool MethodSetElement::operator==(const MethodSetElement& methodSetElement) const {
			return templateVariables() == methodSetElement.templateVariables() &&
				constPredicate() == methodSetElement.constPredicate() &&
				noexceptPredicate() == methodSetElement.noexceptPredicate() &&
				requirePredicate() == methodSetElement.requirePredicate() &&
				returnType() == methodSetElement.returnType() &&
				parameterTypes() == methodSetElement.parameterTypes() &&
				isStatic() == methodSetElement.isStatic();
		}
Пример #3
0
		std::size_t MethodSetElement::hash() const {
			std::size_t seed = 0;
			
			boost::hash_combine(seed, templateVariables().hash());
			boost::hash_combine(seed, constPredicate().hash());
			boost::hash_combine(seed, noexceptPredicate().hash());
			boost::hash_combine(seed, requirePredicate().hash());
			boost::hash_combine(seed, isStatic());
			boost::hash_combine(seed, returnType());
			
			for (const auto& parameterType: parameterTypes()) {
				boost::hash_combine(seed, parameterType);
			}
			
			return seed;
		}
Пример #4
0
		SEM::Value GetTemplatedMethodWithoutResolution(Context& context, SEM::Value value, const SEM::Type* const type, const String& methodName, SEM::ValueArray templateArguments, const Debug::SourceLocation& location) {
			assert(value.type()->isRef() && value.type()->isBuiltInReference());
			if (!type->isObjectOrTemplateVar()) {
				throw ErrorException(makeString("Cannot get method '%s' for non-object type '%s' at position %s.",
					methodName.c_str(), type->toString().c_str(), location.toString().c_str()));
			}
			
			const auto methodSet = getTypeMethodSet(context, type);
			const auto& objectConstPredicate = methodSet->constPredicate();
			
			const auto canonicalMethodName = CanonicalizeMethodName(methodName);
			const auto methodIterator = methodSet->find(canonicalMethodName);
			
			if (methodIterator == methodSet->end()) {
				throw ErrorException(makeString("Cannot find method '%s' for type '%s' at position %s.",
					methodName.c_str(),
					type->toString().c_str(),
					location.toString().c_str()));
			}
			
			const auto& methodElement = methodIterator->second;
			if (methodElement.isStatic()) {
				throw ErrorException(makeString("Cannot access static method '%s' for value of type '%s' at position %s.",
					methodName.c_str(),
					type->toString().c_str(),
					location.toString().c_str()));
			}
			
			auto templateVariableAssignments = type->generateTemplateVarMap();
			
			const auto function = type->isObject() ? type->getObjectType()->functions().at(canonicalMethodName).get() : nullptr;
			
			if (function != nullptr) {
				const auto& templateVariables = function->templateVariables();
				if (templateVariables.size() != templateArguments.size()) {
					// Try to apply some basic deduction...
					if (templateVariables.size() == 1 && templateArguments.size() == 0 &&
						function->constPredicate().isVariable() &&
						function->constPredicate().variableTemplateVar() == templateVariables[0]
					) {
						const auto boolType = getBuiltInType(context, context.getCString("bool"), {});
						templateArguments.push_back(SEM::Value::PredicateExpr(objectConstPredicate.copy(), boolType));
					} else {
						throw ErrorException(makeString("Incorrect number of template "
							"arguments provided for method '%s'; %llu were required, "
							"but %llu were provided at position %s.",
							function->name().toString().c_str(),
							(unsigned long long) templateVariables.size(),
							(unsigned long long) templateArguments.size(),
							location.toString().c_str()));
					}
				}
				
				// Add function template variable => argument mapping.
				for (size_t i = 0; i < templateArguments.size(); i++) {
					const auto templateVariable = templateVariables.at(i);
					const auto& templateValue = templateArguments.at(i);
					
					if (templateValue.isTypeRef()) {
						const auto templateTypeValue = templateValue.typeRefType()->resolveAliases();
						
						if (!templateTypeValue->isObjectOrTemplateVar() || templateTypeValue->isInterface()) {
							throw ErrorException(makeString("Invalid type '%s' passed "
								"as template parameter '%s' for method '%s' at position %s.",
								templateTypeValue->toString().c_str(),
								templateVariable->name().toString().c_str(),
								function->name().toString().c_str(),
								location.toString().c_str()));
						}
						
						templateVariableAssignments.insert(std::make_pair(templateVariable, SEM::Value::TypeRef(templateTypeValue, templateValue.type())));
					} else {
						templateVariableAssignments.insert(std::make_pair(templateVariable, templateValue.copy()));
					}
				}
			} else {
				assert(templateArguments.empty());
			}
			
			const auto methodConstPredicate = methodElement.constPredicate().substitute(templateVariableAssignments);
			
			if (!objectConstPredicate.implies(methodConstPredicate)) {
				throw ErrorException(makeString("Cannot refer to mutator method '%s' from const object of type '%s' at position %s.",
					methodName.c_str(),
					type->toString().c_str(),
					location.toString().c_str()));
			}
			
			// Now check the template arguments satisfy the requires predicate.
			const auto& requirePredicate = methodElement.requirePredicate();
			
			// Conservatively assume require predicate is not satisified if result is undetermined.
			const bool satisfiesRequireDefault = false;
			
			if (!evaluatePredicateWithDefault(context, requirePredicate, templateVariableAssignments, satisfiesRequireDefault)) {
				throw ErrorException(makeString("Template arguments do not satisfy "
					"require predicate '%s' of method '%s' at position %s.",
					requirePredicate.substitute(templateVariableAssignments).toString().c_str(),
					methodName.c_str(),
					location.toString().c_str()));
			}
			
			if (function != nullptr) {
				const auto functionType = simplifyFunctionType(context, function->type().substitute(templateVariableAssignments));
				const auto functionRefType = createFunctionPointerType(context, functionType);
				
				auto functionRef = addDebugInfo(SEM::Value::FunctionRef(type, function, std::move(templateArguments), functionRefType), location);
				
				if (type->isInterface()) {
					const auto interfaceMethodType = createInterfaceMethodType(context, functionType);
					return addDebugInfo(SEM::Value::InterfaceMethodObject(std::move(functionRef), std::move(value), interfaceMethodType), location);
				} else {
					const auto methodType = createMethodType(context, functionType);
					return addDebugInfo(SEM::Value::MethodObject(std::move(functionRef), std::move(value), methodType), location);
				}
			} else {
				const bool isTemplated = true;
				const auto functionType = methodElement.createFunctionType(isTemplated);
				const auto functionRefType = createFunctionPointerType(context, functionType);
				auto functionRef = addDebugInfo(SEM::Value::TemplateFunctionRef(type, methodName, functionRefType), location);
				
				const auto methodType = createMethodType(context, functionType);
				return addDebugInfo(SEM::Value::MethodObject(std::move(functionRef), std::move(value), methodType), location);
			}
		}
Пример #5
0
		MethodSetElement MethodSetElement::withNoExceptPredicate(Predicate newNoExceptPredicate) const {
			return MethodSetElement(templateVariables().copy(), constPredicate().copy(),
				std::move(newNoExceptPredicate),
				requirePredicate().copy(),
				isStatic(), returnType(), parameterTypes().copy());
		}
Пример #6
0
		MethodSetElement MethodSetElement::withRequirement(Predicate requirement) const {
			return MethodSetElement(templateVariables().copy(), constPredicate().copy(),
				noexceptPredicate().copy(),
				Predicate::And(requirePredicate().copy(), std::move(requirement)),
				isStatic(), returnType(), parameterTypes().copy());
		}
Пример #7
0
		MethodSetElement MethodSetElement::copy() const {
			return MethodSetElement(templateVariables().copy(), constPredicate().copy(),
				noexceptPredicate().copy(),
				requirePredicate().copy(),
				isStatic(), returnType(), parameterTypes().copy());
		}