merge
M CMakeLists.txt +4 -4
@@ 409,18 409,18 @@ endif()
 set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/library/.hgtags)
 
 # generate lib id
-find_package(Hg)
+find_package(Hg REQUIRED)
 
 execute_process(
-	COMMAND ${HG_EXECUTABLE} parent --template "{latesttag}"
-	WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/library/
+	COMMAND "${HG_EXECUTABLE}" parent --template "{latesttag}"
+	WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/library/"
 	OUTPUT_VARIABLE KRONOS_CORE_LIBRARY_VERSION
 	RESULT_VARIABLE LIBRARY_VERSION_RESULT
 	OUTPUT_STRIP_TRAILING_WHITESPACE
 )
 
 if(NOT LIBRARY_VERSION_RESULT EQUAL 0)
-	message(FATAL "Failed to determine library version")
+	message(FATAL_ERROR "Failed to determine core library version at ${CMAKE_SOURCE_DIR}/library, using ${HG_EXECUTABLE}")
 endif()
 
 if(NOT ${HG_VERSION_STRING} VERSION_LESS 4)

          
M cmake/Binaryen.cmake +1 -2
@@ 1,5 1,6 @@ 
 set(CMAKE_FIND_ROOT_PATH "")
 set(CMAKE_POSITION_INDEPENDENT_CODE False)
+set(BINARYEN_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/../binaryen/src" CACHE PATH "Binaryen include files")
 
 if (EMSCRIPTEN)
 	set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O2 -s STACK_OVERFLOW_CHECK=2 -s WARN_UNALIGNED=1 -s DEMANGLE_SUPPORT=1 -s DISABLE_EXCEPTION_CATCHING=0 -s DISABLE_EXCEPTION_THROWING=0 -s ASSERTIONS=2")

          
@@ 25,8 26,6 @@ if(NOT ${lib_binaryen} STREQUAL "lib_bin
 		"src/backends/BinaryenCompiler.h"
 		"src/backends/GenericModule.h"
 		"src/backends/CodeGenModule.h")
-
-	include_directories("${BINARYEN_DIR}/src")
 	
 	target_link_libraries(binaryen_backend PUBLIC ${BINARYEN_LIBRARIES})
 	set_target_properties( binaryen_backend PROPERTIES FOLDER libs/emitters )

          
M src/backends/LLVMCompiler.cpp +5 -4
@@ 690,11 690,12 @@ namespace K3 {
 				return v->getType();
 			}).ToVector());
 
-			auto paramsEnd(params);
-			auto paramTypesEnd(paramTypes);
-			paramsEnd.pop_back(); paramTypesEnd.pop_back();
 
 			if (conditionalRecursionLoopCount) {
+				auto paramsEnd(params);
+				paramsEnd.pop_back();
+				paramsEnd.emplace_back(b.getInt(llvm::APInt(32, conditionalRecursionLoopCount, true)));
+
 				params.back() = b.CreateAdd(params.back(), b.getInt32(1), "loopcount", true, true);
 				auto counterZero(b.CreateICmpEQ(params.back(), b.getInt32(conditionalRecursionLoopCount)));
 

          
@@ 785,7 786,7 @@ namespace K3 {
 					returnValue = phi;
 				}
 
-				auto recursionEndFunc(lt.BuildSubroutine("tail", compiledBody, paramTypesEnd));
+				auto recursionEndFunc(lt.BuildSubroutine("tail", compiledBody, paramTypes));
 				for (auto& a : paramAttrVector) recursionEndFunc->addAttribute(a.first, a.second);
 
 				b.SetInsertPoint(counterIsZero);

          
M src/backends/SideEffectCompiler.cpp +48 -17
@@ 640,13 640,20 @@ namespace K3
 
 		CTRef SideEffectTransform::GetDataLayout(CTRef graph) {
 			Deps *m;
-			if (graph->Cast(m)) return GetDataLayout(m->GetUp(0));
+			for (;;) {
+				if (graph->Cast(m)) graph = m->GetUp(0);
+				else break;
+			}
 
 			const DataSource *ds;
 			if (graph->Cast(ds)) return ds->GetDataLayout();
 			else {
 				ResultTypeWithNoArgument rt(graph);
-				return Native::Constant::New(graph->Result(rt), 0);
+				auto resTy = graph->Result(rt);
+				if (resTy.IsNativeType() == false) {
+					std::clog << *graph << " -> " << resTy << "\n";
+				}
+				return Native::Constant::New(resTy, 0);
 			}
 		}
 

          
@@ 806,7 813,7 @@ namespace K3
 					}
 				}
 
-				if (opDrivers.empty()) {
+				if (opDrivers.empty() || opDrivers.find(Type(&Reactive::InitializationDriver)) != opDrivers.end()) {
 					if (!dataDrivers.empty()) {
 						std::cerr << "! Storing undefined value ! <partial -> static>\n" << *finalSrc << " -> " << *finalDst << "\n";
 						for (auto& d : dataDrivers) {

          
@@ 890,7 897,7 @@ namespace K3
 
 			//std::clog << "[src  ] : " << *pureBody << std::endl;
 			//std::clog << "[w/arg] : " << *body << std::endl;
-			//std::cout << "[out  ]: " << *results << std::endl;
+			//std::clog << "[out  ]: " << *results << std::endl;
 
 			elision(body);
 

          
@@ 1000,6 1007,12 @@ namespace K3
 			if (node->Cast(ofs)) return NeverHasData(m->GetUp(0));
 			const DataSource* ds;
 			if (node->Cast(ds)) return NeverHasData(ds->GetDataLayout( ));
+			const VariantTuple* vt;
+			if (node->Cast(vt)) {
+				return
+					NeverHasData(vt->GetUp(0)) &&
+					NeverHasData(vt->GetUp(1));
+			}
 			if (IsPair(node)) {
 				return NeverHasData(First::New(node)) && NeverHasData(Rest::New(node));
 			} else return false;

          
@@ 1255,7 1268,6 @@ namespace K3
 			return IsOfExactType<Pair>(GetDataLayout());
 		}
 
-
 		const DataSource* DataSource::New(CTRef source) {
 			if (IsPair(source)) {
 				auto fst(New(source->GraphFirst()));

          
@@ 1277,6 1289,12 @@ namespace K3
 			return nds;
 		}
 
+		DataSource* DataSource::New(CTRef access, CTRef dataLayout) {
+			auto ds = new DataSource(access, dataLayout);
+			ds->SetReactivity(access->GetReactivity());
+			return ds;
+		}
+
 		const DataSource* DataSource::Conform(SideEffectTransform& sfx, const DataSource* match, CRRef r) const {
 			if (match->IsReference()) {
 				{

          
@@ 1705,7 1723,9 @@ namespace K3
 							umul % dmul != 0 ||
 							ddiv % udiv != 0) {
 							// cache is needed as downstream driver is not an exact fraction of the upstream
-							return FactorBoundaries(sfx, upd, upstreamReactivity, GetReactivity());
+							auto boundaries = FactorBoundaries(sfx, upd, upstreamReactivity, GetReactivity());
+							std::clog << *boundaries << "\n";
+							return boundaries;
 						}
 					}
 				}

          
@@ 2077,14 2097,15 @@ namespace K3
 		};
 
 		CTRef GetDereferencedParams(SideEffectTransform& sfx, Type t, CTRef datum, CRRef rx, std::vector<CTRef>& CallerParams, size_t& ParamID) {
-			if (t.IsUserType()) t = t.UnwrapUserType();
+			while (t.IsUserType()) t = t.UnwrapUserType();
 			if (t.IsPair()) {
 				return Pair::New(
 					GetDereferencedParams(sfx, t.First(), datum->GraphFirst(), rx?rx->First():nullptr, CallerParams, ParamID),
 					GetDereferencedParams(sfx, t.Rest(), datum->GraphRest(), rx?rx->Rest():nullptr, CallerParams, ParamID));
 			} else {
 				datum = DereferenceAll(datum, rx);
-				auto paramData(DataSource::New(SubroutineArgument::In(ParamID++, rx, datum), sfx.GetDataLayout(datum)));
+				auto layout = sfx.GetDataLayout(datum);
+				auto paramData(DataSource::New(SubroutineArgument::In(ParamID++, rx, datum), layout));
 				CallerParams.push_back(sfx.GetDataAccessor(datum));
 				return paramData;
 			}

          
@@ 2104,8 2125,9 @@ namespace K3
 						return GetDereferencedParams(sfx, layout->FixedResult(), datum, rx, callerParams, ParamID);
 				} else {
 					callerParams.push_back(sfx.GetDataAccessor(datum));
+					auto layout = sfx.GetDataLayout(datum);
 					auto arg = SubroutineArgument::New(input, ParamID++, datum, rx);
-					return DataSource::New(arg, sfx.GetDataLayout(datum));
+					return DataSource::New(arg, layout);
 				}
 			} else {
 				return Typed::Nil();

          
@@ 2185,28 2207,38 @@ namespace K3
 		static CTRef _SubstituteTypeToArgumentGraph(CTRef Argument, CTRef Type, bool splitPairs) {
 			const DataSource *ds;
 			if (Argument->Cast(ds)) {
-				return DataSource::New(ds->GetAccessor(), _SubstituteTypeToArgumentGraph(ds->GetDataLayout(), Type, false));
+				return DataSource::New(
+					ds->GetAccessor(),
+					_SubstituteTypeToArgumentGraph(ds->GetDataLayout(), Type, false));
 			}
 
 			if (IsPair(Argument)) {
 				if (splitPairs) {
-					return Pair::New(_SubstituteTypeToArgumentGraph(Argument->GraphFirst(), Type->GraphFirst()),
+					return Pair::New(
+						_SubstituteTypeToArgumentGraph(Argument->GraphFirst(), Type->GraphFirst()),
 						_SubstituteTypeToArgumentGraph(Argument->GraphRest(), Type->GraphRest()));
-				} else return Type;
+				} else {
+					return Type;
+				}
 			}
 
 
-			if (Argument->Cast<Native::Constant>() || Argument->Cast<VariantTuple>()) {
-				Native::Constant *c;
+			if (Native::Constant* c = Argument->Cast<Native::Constant>()) {
 				if (Argument->Cast(c)) {
 					if (c->FixedResult().IsPair() == false) return c;
+				} else {
+					return Type;
 				}
-				return Type;
 			}
 
 			const Reference* ref;
 			if (Argument->Cast(ref)) {
-				return Reference::New(_SubstituteTypeToArgumentGraph(ref->GetUp(0), Type, splitPairs));
+				return Reference::New(_SubstituteTypeToArgumentGraph(ref->GetUp(0), Type, false));
+			}
+
+			if (Type->Cast<VariantTuple>()) {
+				assert(!splitPairs);
+				return Type;
 			}
 
 			return Argument;

          
@@ 2387,7 2419,6 @@ namespace K3
 			//std::cout << "RecursionBranch Argument: " << *ArgumentGraph << std::endl;
 			//std::cout << "Sequence        Result  : " << *SequenceResult << std::endl;
 			//std::cout << "RecursionBranch Result  : " << *ResultGraph << std::endl;
-			//std::cout << "arg " << *argumentReactivity << "\n" << *GetReactivity() << "\n";
 
 			/* add counter argument */
             SubroutineArgument::In(ParamID++, nullptr, Type::Int32, "count");

          
M src/common/Ref.h +1 -1
@@ 96,7 96,7 @@ public:
 		if (ptr) ptr->Attach();
 	}
 
-	Ref(Ref&& source)
+	Ref(Ref&& source) noexcept
 	{
 		ptr = source.ptr;
 		source.ptr = 0;

          
M src/k3/CompilerNodes.h +1 -5
@@ 29,11 29,7 @@ namespace K3 {
 			DataSource(CTRef accessPath, CTRef dataLayout):TypedBinary(accessPath,dataLayout){}
 		PUBLIC
 			bool CanTakeReference() const;
-			static DataSource* New(CTRef access, CTRef dataLayout) {
-				auto ds = new DataSource(access,dataLayout);
-				ds->SetReactivity(access->GetReactivity());
-				return ds;
-			}
+			static DataSource* New(CTRef access, CTRef dataLayout);
 			static const DataSource* New(CTRef source);
 			CTRef GraphFirst() const override;
 			CTRef GraphRest() const override;

          
M src/k3/SmallContainer.h +1 -1
@@ 155,7 155,7 @@ namespace Sml{
 			*this = std::move(source);
 		}
 
-		Set& operator=(Set&& source) {
+		Set& operator=(Set&& source) noexcept {
 			if (set) delete set;
 			for(unsigned k(0);k<source._size;++k) owned[k]=source.owned[k];
 			_size = source._size;