* Overloading for functions (complete) gscript

Wed, 08 Apr 2015 16:39:57 +0300

author
cemkalyoncu
date
Wed, 08 Apr 2015 16:39:57 +0300
branch
gscript
changeset 678
43628e4a946a
parent 677
8f14e56a27d6
child 679
ffe46ff782d7

* Overloading for functions (complete)
- Phase 8: Checks

Source/Scripting/Embedding.h file | annotate | diff | comparison | revisions
Source/Scripting/Reflection.h file | annotate | diff | comparison | revisions
--- a/Source/Scripting/Embedding.h	Wed Apr 08 11:07:07 2015 +0300
+++ b/Source/Scripting/Embedding.h	Wed Apr 08 16:39:57 2015 +0300
@@ -136,6 +136,8 @@
 		template<class T_>
 		struct extractvector {
 			enum { isvector = false };
+			
+			using inner = T_;
 		};
 
 		template<template<class, class> class V_, class T_, class A_>
@@ -213,6 +215,12 @@
 			ASSERT((!returnsref || (returntype==Scripting::Variant && data.GetValue<Data>().IsReference())), 
 				   "Embedded function does not return a reference");
 			
+			if(returnsref && returntype==Scripting::Variant) {
+				if(!data.GetValue<Data>().IsReference()) {
+					throw CastException("Non-reference variant", "Reference variant", "While returning value from "+parent->GetName());
+				}
+			}
+			
 			return data;
 		}
 
@@ -244,6 +252,169 @@
 
 		template<int P_>
 		void checkparam() {
+			using T=param<P_>;
+			TMP::AbstractRTTC<typename std::remove_pointer<T>::type> rtt;
+			
+			bool ismember=parent->IsMember() && !parent->IsStatic();
+
+			//** Constant and reference checks
+			if(is_nonconstref<T>::value || (std::is_pointer<T>::value && !std::is_const<typename std::remove_pointer<T>::type>::value)) {
+				if(P_==0 && ismember) {
+					ASSERT(
+						!IsConstant(), 
+						"This function variant is marked as const, yet its implementation requires non-const "
+						"pointer or reference\n"
+						"in function "+parent->GetName()
+					);
+				}
+				else {
+					const auto &param=parameters[P_-ismember];
+					
+					ASSERT(
+						P_-ismember!=parameters.size()-1 || !repeatlast, 
+						"Repeating parameter vectors cannot be non-const references"
+					);
+					
+					ASSERT(param.IsReference(),
+						"Parameter #"+String::From(P_-ismember)+" is not declared as reference, "
+						"yet its implementation is\n"
+						"in function "+parent->GetName()
+					);
+					
+					ASSERT(!param.IsConstant(),
+						"Parameter #"+String::From(P_-ismember)+" is declared as constant, "
+						"yet its implementation is not const\n"
+						"in function "+parent->GetName()
+					);
+				}
+			}
+			else if(std::is_pointer<T>::value) {
+				if(P_==0 && ismember) {
+#ifdef TEST
+					if(!IsConstant()) {
+						std::cout<<"This function variant is not marked as const, yet its implementation requires const "
+						"pointer or reference\n"
+						"in function "+parent->GetName()<<std::endl;
+					}
+#endif
+				}
+				else {
+					const auto &param=parameters[P_-ismember];
+					
+					ASSERT(
+						P_-ismember!=parameters.size()-1 || !repeatlast, 
+						"Repeating parameter vectors cannot be a pointer"
+					);
+					
+					ASSERT(param.IsReference(),
+						   "Parameter #"+String::From(P_-ismember+1)+" is not declared as reference, "
+						   "yet its implementation is\n"
+						   "in function "+parent->GetName()
+					);
+					
+#ifdef TEST
+					if(!IsConstant()) {
+						std::cout<<"This function variant is not marked as const, yet its implementation requires const "
+						"pointer or reference\n"
+						"in function "+parent->GetName()<<std::endl;
+					}
+#endif
+				}
+			}
+			else if(std::is_reference<T>::value) { //const ref can be anything
+				//nothing to do
+			}
+			else if(std::is_const<T>::value) { //constant value type
+				if(P_==0 && ismember) {
+					ASSERT(
+						IsConstant(), 
+						"This function variant is marked as a non-const member function, "
+						"yet its implementation requests a constant value which cannot modify the this pointer.\n"
+						"in function "+parent->GetName()
+					);
+				}
+				else {
+					const auto &param=parameters[P_-ismember];
+					
+					if(P_-ismember!=parameters.size()-1 || !repeatlast) {
+						ASSERT(!param.IsReference(),
+							"Parameter #"+String::From(P_-ismember+1)+" is declared as reference "
+							"yet its implementation not\n"
+							"in function "+parent->GetName()
+						);
+						
+#ifdef TEST
+						if(!IsConstant()) {
+							std::cout<<"This function variant is not marked as const, yet its implementation requires const "
+							"value\n"
+							"in function "+parent->GetName()<<std::endl;
+						}
+#endif
+					}
+				}
+			}
+			else { //normal value type
+				if(P_==0 && ismember) {
+					ASSERT(
+						IsConstant(), 
+						"This function variant is marked as a non-const member function, "
+						"yet its implementation requests a value which cannot modify the this pointer.\n"
+						"in function "+parent->GetName()
+					);
+				}
+				else {
+					const auto &param=parameters[P_-ismember];
+					
+					if(P_-ismember!=parameters.size()-1 || !repeatlast) {
+						ASSERT(!param.IsReference(),
+							"Parameter #"+String::From(P_-ismember+1)+" is declared as reference, "
+							"yet its implementation not\n"
+							"in function "+parent->GetName()
+						);
+						
+						ASSERT(!param.IsConstant(),
+							"Parameter #"+String::From(P_-ismember+1)+" is declared as constant, "
+							"yet its implementation is not const\n"
+							"in function "+parent->GetName()
+						);
+					}
+				}
+			}
+			
+			//type check
+			if(P_==0 && ismember) {
+				ASSERT(
+					(rtt.NormalType==parent->GetOwner().TypeInterface.NormalType),
+					"The declared type ("+parent->GetOwner().GetName()+", "+
+					parent->GetOwner().TypeInterface.NormalType.Name()+") of "
+					"parameter #"+String::From(P_-ismember+1)+" does not match with the function type ("+
+					rtt.NormalType.Name()+")\n"+
+					"in function "+parent->GetName()
+				);
+			}
+			else if(P_-ismember==parameters.size()-1 && repeatlast) {
+				const auto &param=parameters[P_-ismember];
+				
+				ASSERT(
+					(TMP::RTT<typename extractvector<T>::inner>()==param.GetType().TypeInterface.NormalType),
+					"The declared type ("+parent->GetOwner().GetName()+", "+
+					parent->GetOwner().TypeInterface.NormalType.Name()+") of "
+					"parameter #"+String::From(P_-ismember+1)+" does not match with the function type ("+
+					rtt.NormalType.Name()+")\n"+
+					"in function "+parent->GetName()
+				);
+			}
+			else {
+				const auto &param=parameters[P_-ismember];
+				
+				ASSERT(
+					rtt.NormalType==param.GetType().TypeInterface.NormalType,
+					"The declared type ("+param.GetType().GetName()+", "+param.GetType().TypeInterface.NormalType.Name()+") of "
+					"parameter #"+String::From(P_-ismember+1)+" does not match with the function type ("+
+					rtt.NormalType.Name()+")\n"
+					"in function "+parent->GetName()
+				);
+			}
 		}
 		
 		template<int ...S_>
--- a/Source/Scripting/Reflection.h	Wed Apr 08 11:07:07 2015 +0300
+++ b/Source/Scripting/Reflection.h	Wed Apr 08 16:39:57 2015 +0300
@@ -519,7 +519,9 @@
 				ASSERT(!isoperator || var.parameters.size()==1, "Operators should have only a single parameter");
 
 				var.parent=this;
+#ifndef NDEBUG
 				var.dochecks(false);
+#endif
 				variants.Push(var);
 			}
 			
@@ -527,7 +529,9 @@
 				ASSERT(!isoperator, "Operators cannot be methods");
 				
 				var.parent=this;
+#ifndef NDEBUG
 				var.dochecks(true);
+#endif
 				methods.Push(var);
 			}
 			

mercurial