You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by jb...@apache.org on 2010/06/12 21:34:24 UTC

svn commit: r954053 - /commons/sandbox/gsoc/2010/scxml-js/trunk/test/xslt/AbstractStatechartGenerator.xsl

Author: jbeard
Date: Sat Jun 12 19:34:24 2010
New Revision: 954053

URL: http://svn.apache.org/viewvc?rev=954053&view=rev
Log:
Intermediate commit. AbstractStatechartGenerator.xsl might be close to being hooked up.

Modified:
    commons/sandbox/gsoc/2010/scxml-js/trunk/test/xslt/AbstractStatechartGenerator.xsl

Modified: commons/sandbox/gsoc/2010/scxml-js/trunk/test/xslt/AbstractStatechartGenerator.xsl
URL: http://svn.apache.org/viewvc/commons/sandbox/gsoc/2010/scxml-js/trunk/test/xslt/AbstractStatechartGenerator.xsl?rev=954053&r1=954052&r2=954053&view=diff
==============================================================================
--- commons/sandbox/gsoc/2010/scxml-js/trunk/test/xslt/AbstractStatechartGenerator.xsl (original)
+++ commons/sandbox/gsoc/2010/scxml-js/trunk/test/xslt/AbstractStatechartGenerator.xsl Sat Jun 12 19:34:24 2010
@@ -1,6 +1,7 @@
 <?xml version="1.0"?>
 <stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" 
 	xmlns:s="http://www.w3.org/2005/07/scxml"
+	xmlns:c="https://svn.apache.org/repos/asf/commons/sandbox/gsoc/2010/scxml-js/trunk/"
 	version="1.0">
 	<output method="text"/>
 
@@ -9,6 +10,27 @@
 	<param name="noMap" select="true()"/>
 	<param name="name"/>
 
+	<!-- these params get overridden by subclasses -->
+	<param name="dispatchInvocation"/>
+	<param name="currentConfigurationExpression"/>
+	<param name="defaultEventLiteral"/>
+
+	<!--//*[(self::state or self::parallel or self::final or self::initial or self::scxml or self::history) and not(.//*[(self::state or self::parallel or self::final or self::initial or self::scxml or self::history)])]-->
+	<!--TODO: hook up namespaces -->
+	<variable name="allStates" select="//*[(self::state or self::parallel or self::final or self::initial or self::scxml or self::history)]"/>
+	<variable name="states" select="//s:state"/>
+	<variable name="parallels" select="//s:parallel"/>
+	<variable name="finals" select="//s:final"/>
+	<variable name="initials" select="//s:initial"/>
+	<variable name="transitions" select="//s:transition"/>
+	<variable name="defaultTransitions" select="//s:transition[not(@event)]"/>
+	<variable name="nonDefaultTransitions" select="//s:transition[@event]"/>
+	
+	<variable name="basicStates" select="$allStates[not(.//*[(self::state or self::parallel or self::final or self::initial or self::scxml or self::history)])]"/>
+	<variable name="compositeStates" select="$allStates[.//*[(self::state or self::parallel or self::final or self::initial or self::scxml or self::history)]]"/>
+	<variable name="parallelRegions" select="$parallels/s:state"/>
+
+
 	<template match="/s:scxml">
 
 		<if test="$noIndexOf">
@@ -30,34 +52,40 @@
 				</call-template>
 
 				//states
-				<for-each select=".//s:state | .//s:initial | .//s:parallel ">
+				<for-each select="$allStates">
 					<call-template name="genState">
 						<with-param name="state" select="."/>
 					</call-template>
 				</for-each>
 
 		
-				<!--
 				//states enum for glass-box unit testing
-				{self.genStatesEnum(conf.basicStates)}
+				<for-each select="$basicStates">
+					<call-template name="genStatesEnum">
+						<with-param name="state" select="."/>
+					</call-template>
+				</for-each>
 
 				//trigger methods for synchronous interaction
-				{util.foreach(conf.nonDefaultTransitions,self.genExternalTriggerDispatcher)}
+				<for-each select="$nonDefaultTransitions">
+					<call-template name="genExternalTriggerDispatcher">
+						<with-param name="t" select="."/>
+					</call-template>
+				</for-each>
 
-				{self.genContextHooks()}
+				<call-template name="genContextHooks"/>
 
 				//initialization script
-				{conf.scxml.script.toString()}
+				<value-of select="script"/>
 
 				//initialization method
-				{self.genInitialization()}
+				<call-template name="genInitialization"/>
 
 				//internal runtime functions
-				{self.genInternalRuntimeFunctions()}
+				<call-template name="genInternalRuntimeFunctions"/>
 
 				//start static boilerplate code
-				{self.genBoilerplateDispatchCode(conf.dispatchInvocation)}
-				-->
+				<call-template name="genBoilerplateDispatchCode"/>
 
 			}
 
@@ -84,6 +112,7 @@
 
 		<variable name="parentName">
 			<choose>
+				<!-- FIXME: probably want to refine this query, as we may not be able to assume that all states have ids?-->
 				<when test="$state/../@id">
 					<value-of select="$state/../@id"/>
 				</when>
@@ -112,8 +141,8 @@
 
 				this.initial = null;
 
-				<!--FIXME-->
-				this.depth = {self.computeDepth(state)};
+				<!--FIXME: we add depth attribute to state-->
+				this.depth = <value-of select="$state/@c:depth"/>;
 
 				this.historyState = null;
 
@@ -150,17 +179,17 @@
 						this.historyState.lastConfiguration = currentConfiguration.slice();
 					</if>
 
+					}
+				}
 
 					<for-each select="$state/onexit/*">
-						<call-template name="genExecutableContent">
-							<with-param name="executableNode" select="."/>
-						</call-template>
+						<apply-templates select="s:if | s:raise | s:log | s:script | s:send | s:cancel | s:invoke | s:finalize | s:datamodel | s:data | s:assign | s:validate | s:param"/>
 					</for-each>
 
 				}
 
 				<call-template name="genStateHooks">
-					<with-param name="state" select="."/>
+					<with-param name="state" select="$state"/>
 				</call-template>
 				
 
@@ -171,10 +200,113 @@
 
 	</template>
 
-	<template name="genExecutableContent">
-		<param name="executableNode"/>
 
-		//executable content goes here
+	<template name="genStatesEnum">
+		<param name="states"/>
+
+		this._states = {
+			<for-each select="$states">
+				<value-of select="@id"/> : <value-of select="@id"/>
+				<if test="not(position() = last())">,</if>
+			</for-each>
+		}
+	</template>
+
+	<!-- executable content section-->
+
+	<!-- base profile -->
+
+	<!-- TODO: transform DOM to this intermediate format -->
+	<!--
+		<s:if cond="">
+			<c:executableContent>
+				...
+			</c:executableContent>
+			<s:elseif cond="">
+				<c:executableContent>
+					...
+				</c:executableContent>
+			</s:elseif>
+			...
+			<s:else>
+				<c:executableContent>
+					...
+				</c:executableContent>
+			</s:else>
+		</s:if>
+	-->
+	<template match="s:if">
+		if (<value-of select="@cond"/>) {
+			<apply-templates select="c:executableContent/*">	<!--TODO:some filtering here?-->
+		}
+		<apply-templates select="s:elseif"/>
+		<apply-templates select="s:else"/>
+	</template>
+
+	<template match="s:elseif">
+		else if (<value-of select="@cond"/>) {
+			<apply-templates select="c:executableContent/*">	<!--TODO:some filtering here?-->
+		}
+	</template>
+
+	<template match="s:else">
+		else {
+			<apply-templates select="c:executableContent/*">	<!--TODO:some filtering here?-->
+		}
+	</template>
+
+	<template match="s:log">
+		console.log(' <value-of select="@label"/> : ' +  <value-of select="@expr"/> ); 
+	</template>
+
+	<template match="s:raise">
+	<!--TODO-->
+	</template>
+
+	<!-- script module -->
+
+	<template match="s:script">
+		<value-of select="."/>
+	</template>
+
+	<!-- external communications module -->
+
+	<template match="s:send">
+	<!--TODO-->
+	</template>
+
+	<template match="s:cancel">
+	<!--TODO-->
+	</template>
+
+	<template match="s:invoke">
+	<!--TODO-->
+	</template>
+
+	<template match="s:finalize">
+	<!--TODO-->
+	</template>
+
+	<!-- data module -->
+
+	<template match="s:datamodel">
+	<!--TODO-->
+	</template>
+
+	<template match="s:data">
+	<!--TODO-->
+	</template>
+
+	<template match="s:assign">
+	<!--TODO-->
+	</template>
+
+	<template match="s:validate">
+	<!--TODO-->
+	</template>
+
+	<template match="s:param">
+	<!--TODO-->
 	</template>
 
 	<template name="genStateHooks">
@@ -209,5 +341,116 @@
 		}
 	</template>
 
+
+	<!-- abstract templates that we expect to be refined in subclasses -->
+
+	<template name="genInternalRuntimeFunctions">
+		function sortByDepthDeepToShallow(a,b){
+			return b.depth - a.depth;
+		}
+	</template>
+
+
+	<template name="genBoilerplateDispatchCode">
+		//static private member variables
+		var currentConfiguration = []; //current configuration
+		var innerEventQueue = []; //inner event queue
+		var outerEventQueue = []; //outer event queue
+		var isInStableState = true;
+		var isPreempted = false;
+		var hasTakenDefaultTransition = false;
+		var destroyed = false;
+		var mainLoopCallback = null;
+
+		//static private member functions
+		function mainLoop() {
+
+			if(!destroyed){
+				//take an event from the current outer event queue
+				if (outerEventQueue.length &amp;&amp; isInStableState) {
+					runToCompletion(outerEventQueue.shift());
+				}
+				//call back
+				mainLoopCallback = window.setTimeout(function() {
+					mainLoop(); //FIXME: note that when calling mainloop this way, we won't have access to the "this" object. 
+					//I don't think we ever use it though. Everything we need is private in function scope.
+				},
+				100);
+			}
+		}
+
+		function runToCompletion(e){
+			isInStableState = false;
+
+			if(e){
+				innerEventQueue.push(e);
+			}
+
+			do{
+				//take any available default transitions
+				microstep(<value-of name="defaultEventLiteral"/>});
+
+				if(!hasTakenDefaultTransition){
+					
+					if(!innerEventQueue.length){
+						//we have no more generated events, and no default transitions fired, so
+						//we are done, and have run to completion
+						break;
+					}else{
+						//microstep, then dequeue next event sending in event
+						microstep(innerEventQueue.shift());
+					}
+				}else{
+					//he has taken a default transition, so reset the global variable to false and loop again
+					hasTakenDefaultTransition = false;
+				}
+
+			}while(true)
+
+			isInStableState = true;
+		}
+
+		function microstep(e){
+			currentConfiguration.forEach(function(state){
+				if(!isPreempted) 
+					<value-of select="$dispatchInvocation"/>
+			});
+
+			//reset the isPreempted flag
+			isPreempted = false;
+		}
+
+
+		this.destroy = function(){
+			//right now, this only disables timer and sets global destroyed variable to prevent future callbacks
+			window.clearTimeout(mainLoopCallback);
+			mainLoopCallback = null;
+			destroyed = true;
+		}
+
+
+		//this is for async communication
+		this.GEN = function(e){
+			outerEventQueue.push(e);
+		}
+
+		//this may or may not be something we want to expose, but for right now, we at least need it for testing
+		this.getCurrentConfiguration = function(){
+			//slice it to return a copy of the configuration rather than the conf itself
+			//this saves us all kinds of confusion involving references and stuff
+			return <value-of select="$currentConfigurationExpression"/>;
+		}
+
+		//end static boilerplate code
+	</template>
+
+	<template name="genContextHooks"/>
+	<template name="genStateHooks"/>
+	<template name="genExternalTriggerDispatcher"/>
+	<template name="genParallelSubstateConfigurationSetString"/>
+	<template name="genNonParallelSubstateConfigurationSetString"/>
+	<template name="genInitialization"/>
+	<template name="genTriggerDispatcherContext"/>
+
 </stylesheet>