<commit_before>/**
 * Copyright (c) 2017 committers of YAKINDU and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     committers of YAKINDU - initial API and implementation
 */
package org.yakindu.sct.generator.cpp.eventdriven

import com.google.inject.Inject
import java.util.List
import org.yakindu.base.types.Direction
import org.yakindu.sct.generator.cpp.StatemachineImplementation
import org.yakindu.sct.model.sexec.ExecutionFlow
import org.yakindu.sct.model.sgraph.Scope
import org.yakindu.sct.model.stext.stext.EventDefinition
import org.yakindu.sct.model.stext.stext.ImportScope
import org.yakindu.sct.model.stext.stext.StatechartScope

/*
 * To restore the event queue for in events, revert commit 235659d
 */
/**
 * @author <NAME> - Initial contribution and API
 */
class EventDrivenStatemachineImplementation extends StatemachineImplementation {
	@Inject extension EventNaming eventNaming
	
	override additionalFunctions(ExecutionFlow it) {
		'''
		«nextEventFunction»
		
		«generateInternalDispatchEventFunction»
		
		«generateInterfaceDispatchFunctions»
		'''
	}
	
	override protected usingNamespaces(ExecutionFlow it) {
		'''using namespace «eventNamespaceName»;'''
	}
	
	
	override raiseTimeEventFunction(ExecutionFlow it) '''
		void «module»::«raiseTimeEventFctID»(sc_eventid evid)
		{
			if ((evid >= (sc_eventid)«timeEventsInstance») && (evid < (sc_eventid)(&«timeEventsInstance»[«timeEventsCountConst»])))
			{
				*(sc_boolean*)evid = true;
				runCycle();
			}				
		}
	'''
	
	override runCycleFunction(ExecutionFlow it) { 
	'''
		void «module»::runCycle()
		{
			clearOutEvents();
			
			SctEvent * currentEvent = getNextEvent();
			
			do
			{
				/* Set event flags as usual */
				dispatch_event(currentEvent);
				
				«runCycleFunctionForLoop»
				
				/* Delete event from memory */
				delete currentEvent;
				clearInEvents();
			} while((currentEvent = getNextEvent()));
		}
	'''
	}
	
	def getNextEventFunction(ExecutionFlow it) {
		'''
		SctEvent* «module»::getNextEvent()
		{
			SctEvent* nextEvent = 0;
			
			if(!internalEventQueue.empty()) {
				nextEvent = internalEventQueue.front();
				internalEventQueue.pop_front();
			}
			
			return nextEvent;
		}
		'''
	}
	
	override constructorDefinition(ExecutionFlow it) {
	val List<String> toInit = newArrayList
	toInit.addAll(getInterfaces.map[instance].map[i|'''«i»(this)'''])
	'''
		«module»::«module»() :
			«FOR init : toInit SEPARATOR ","»
				«init»
			«ENDFOR»
		{
			«constructorBody(it)»
		}
	'''
	}
	
	override constructorBody(ExecutionFlow it)
		'''
		«super.constructorBody(it)»
		
		'''
	
	
	def generateInterfaceDispatchFunctions(ExecutionFlow it) {
		'''
		«FOR s : statechartScopes»
		«generateInterfaceDispatchFunction(s)»
		«ENDFOR»
		'''
	}

	def dispatch generateInterfaceDispatchFunction(ExecutionFlow it, ImportScope s) {}

	def dispatch generateInterfaceDispatchFunction(ExecutionFlow it, Scope s) {
		'''
			«val localEvents = s.declarations.filter(EventDefinition).filter[direction == Direction::LOCAL]»
			«IF localEvents.size > 0»
				void «module»::«s.interfaceName»::dispatch_event(SctEvent * event)
				{
					switch(event->name)
					{
						«FOR e : localEvents»
							case «e.eventEnumMemberName»:
							{
								«IF e.hasValue»
									«e.eventClassName» * e = dynamic_cast<«e.eventClassName»*>(event);
									if(e != 0) {
										internal_«e.asRaiser»(e->value);
									}
								«ELSE»
									internal_«e.asRaiser»();
								«ENDIF»<commit_msg>Change dynamic_cast to static_cast, fix #2011<commit_after>/**
 * Copyright (c) 2017 committers of YAKINDU and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     committers of YAKINDU - initial API and implementation
 */
package org.yakindu.sct.generator.cpp.eventdriven

import com.google.inject.Inject
import java.util.List
import org.yakindu.base.types.Direction
import org.yakindu.sct.generator.cpp.StatemachineImplementation
import org.yakindu.sct.model.sexec.ExecutionFlow
import org.yakindu.sct.model.sgraph.Scope
import org.yakindu.sct.model.stext.stext.EventDefinition
import org.yakindu.sct.model.stext.stext.ImportScope
import org.yakindu.sct.model.stext.stext.StatechartScope

/*
 * To restore the event queue for in events, revert commit 235659d
 */
/**
 * @author <NAME> - Initial contribution and API
 */
class EventDrivenStatemachineImplementation extends StatemachineImplementation {
	@Inject extension EventNaming eventNaming
	
	override additionalFunctions(ExecutionFlow it) {
		'''
		«nextEventFunction»
		
		«generateInternalDispatchEventFunction»
		
		«generateInterfaceDispatchFunctions»
		'''
	}
	
	override protected usingNamespaces(ExecutionFlow it) {
		'''using namespace «eventNamespaceName»;'''
	}
	
	
	override raiseTimeEventFunction(ExecutionFlow it) '''
		void «module»::«raiseTimeEventFctID»(sc_eventid evid)
		{
			if ((evid >= (sc_eventid)«timeEventsInstance») && (evid < (sc_eventid)(&«timeEventsInstance»[«timeEventsCountConst»])))
			{
				*(sc_boolean*)evid = true;
				runCycle();
			}				
		}
	'''
	
	override runCycleFunction(ExecutionFlow it) { 
	'''
		void «module»::runCycle()
		{
			clearOutEvents();
			
			SctEvent * currentEvent = getNextEvent();
			
			do
			{
				/* Set event flags as usual */
				dispatch_event(currentEvent);
				
				«runCycleFunctionForLoop»
				
				/* Delete event from memory */
				delete currentEvent;
				clearInEvents();
			} while((currentEvent = getNextEvent()));
		}
	'''
	}
	
	def getNextEventFunction(ExecutionFlow it) {
		'''
		SctEvent* «module»::getNextEvent()
		{
			SctEvent* nextEvent = 0;
			
			if(!internalEventQueue.empty()) {
				nextEvent = internalEventQueue.front();
				internalEventQueue.pop_front();
			}
			
			return nextEvent;
		}
		'''
	}
	
	override constructorDefinition(ExecutionFlow it) {
	val List<String> toInit = newArrayList
	toInit.addAll(getInterfaces.map[instance].map[i|'''«i»(this)'''])
	'''
		«module»::«module»() :
			«FOR init : toInit SEPARATOR ","»
				«init»
			«ENDFOR»
		{
			«constructorBody(it)»
		}
	'''
	}
	
	override constructorBody(ExecutionFlow it)
		'''
		«super.constructorBody(it)»
		
		'''
	
	
	def generateInterfaceDispatchFunctions(ExecutionFlow it) {
		'''
		«FOR s : statechartScopes»
		«generateInterfaceDispatchFunction(s)»
		«ENDFOR»
		'''
	}

	def dispatch generateInterfaceDispatchFunction(ExecutionFlow it, ImportScope s) {}

	def dispatch generateInterfaceDispatchFunction(ExecutionFlow it, Scope s) {
		'''
			«val localEvents = s.declarations.filter(EventDefinition).filter[direction == Direction::LOCAL]»
			«IF localEvents.size > 0»
				void «module»::«s.interfaceName»::dispatch_event(SctEvent * event)
				{
					switch(event->name)
					{
						«FOR e : localEvents»
							case «e.eventEnumMemberName»:
							{
								«IF e.hasValue»
									«e.eventClassName» * e = static_cast<«e.eventClassName»*>(event);
									if(e != 0) {
										internal_«e.asRaiser»(e->value);
									}
								«ELSE»
									internal_«e.asRaiser»();
								«ENDIF»
{'fraction_non_alphanumeric': 0.12437877770315649, 'fraction_numerical': 0.0051040967092008055, 'mean_word_length': 3.797680412371134, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '426131', 'n_tokens_mistral': 2881, 'n_tokens_neox': 2363, 'n_words': 635}