SMC FAQ

Question Index


Miscellaneous Questions

What is the current SMC version?

The current version 6.3.0, released September 2, 2013.

What Java version does SMC need?

SMC needs Java 1.7 or better.

My software only runs on Java 6. Now that SMC runs on Java 7, is the generated code still Java 6 compatible?

Yes, SMC still generates Java 6 compatible code by default. The only caveat is when you using the SMC options -reflect and -generic7. This will generate Java 7 code which is incompatible with Java 6. For Java 6, use the options -reflect and -generic or just -reflect.

Where is the documentation?

Go here for the SMC programmer's manual. It explains how to write, compile and debug SMC finite state machines. You can also download the programmer's manual for quick, off-line reference.

Go here for the Java docs covering the SMC model, parser and generator packages.

Where do I download SMC?

At http://sourceforge.net/projects/smc in the "Latest File Releases" section.

Where are the SMC documents in PDF?

The programmer's manual is not available in PDF and there are no plans to provide the manual in any format other than HTML.

How do I contact SMC developers?

The best place to start is at http://sourceforge.net/projects/smc in the "Public Areas" section which contains links to:

SMC developers are signed up to receive e-mail notification when new bugs are submitted or new articles added to the discussion forums. We will get back to you as soon as possible.

Finally, if what you really want to do is e-mail an SMC developer, the "Developer Info" box at the top of SMC project page lists all SMC developers. Note: You must be logged into SourceForge to send e-mail this way. That means you must be a SourceForge member - which is a pretty good idea. Go here to sign up as a SourceForge member.

If you are not a SourceForge member, you can send e-mail directly to me.

Is the SMC license GPL compatible?

Yes, it is as per the Gnu Open Source license review. SMC uses MPL 1.1 and its license does contain section 13 which allows the use of GPL.

Does the SMC license cover the files SMC generates?

No. The .sm files and the output files SMC generates from .sm files belong to you and are covered by your copyright (if you are using one.)

The SMC license covers those files associated with SMC (including but not limited to the source files implementing SMC, the supporting C++/Java/[incr Tcl]/VB.net/C# libraries, C++ .h files, etc.)

Note: If you do use a copyright comment in your source code, then I suggest placing that comment within the verbatim code block ( %{ ... %} ) at the top of you .sm file. SMC will place this comment at the top of the generated files (except the *_sm.h if the target language is C++).

If I change the SMC namespace/package, must I make the change publicly available?

No. In this instance you have not changed SMC's functionality. I do not require making this insignificant change publicly available.

Is this a rip-off of Robert C. Martin's state machine compiler?

No, it is not a rip-off but yes it is descended from Robert Martin's SMC. There is a more detailed explanation in the SMC User's Manual preface.

Why not have the context class inherit from the application class?

Because:

  1. SMC is designed to be as loosely-coupled with your application code as possible. The SMC Programmer's Manual section 3 shows just how little code it takes to hook an SMC-generated state machine into your class.
  2. Robert Martin's FSM pattern is not as loosely-coupled as I would like.

With Robert Martin's pattern, you write the Turnstile class and and then have AppClassFSM inherit from Turnstile. You then instantiate the TurnstileFSM class and work with that object. I think this is unnatural. My inclination is to instantiate Turnstile because that is what corresponds to the "real" world.

SMC does a variation on this theme. It generates a TurnstileContext class which inherits from FSMContext class and keeps a reference to the Turnstile object which instantiated it. TurnstileContext stores the current state and defines the "transition" methods which Turnstile calls when it issues a transition.

For a more detailed explanation of what patterns SMC uses, see the SMC Programmer's Manual, section 5 .

Why doesn't your SMC support state inheritance?

Because by the time I learned of this feature in Robert Martin's SMC, I had already added the default state and default transition feature to this SMC. State inheritance and default state/transition play the same roll: allow a transition to have virtual definitions. If the transition is not explicitly defined in the current state, then fall back on another definition. With state inheritance, you use the super state's definition. With the default states/transition, you use the next default in the chain.

See the SMC Programmer's Manual, section 5 for more about default transitions.

Why write SMC in Java?

Actually, it wasn't in Java originally. It was written in C/LEX/YACC. But I wanted to run SMC on multiple platforms like the various Unices, Linux, Windows and Macintosh. Porting the C/LEX/YACC combination to those platforms would have been a real headache.

So I instead ported SMC to a platform-independent language. I re-wrote the lexer and parser as an SMC finite state machines. Now SMC will run on whatever platform Java runs on - which includes the vast majority of boxes.

What programming languages does SMC support?

SMC generates code for the following object-oriented programming languages:

  1. C
  2. C++
  3. C#
  4. [incr Tcl]
  5. Groovy
  6. Java
  7. Lua
  8. Objective-C
  9. Perl
  10. PHP
  11. Python
  12. Ruby
  13. Scala
  14. VB.net
(And there are more to follow ...)

How come SMC doesn't support Smalltalk/CLOS/Eiffel/name-your-favorite-object-oriented-language?

Simple. I haven't done it yet and I have never used those languages. So before I can add support for those languages, I first need to study them and get a compiler/development environment. That will take some time because SMC is not my full time job.

Of course, this being an open source project and SMC's code is loaded on to a publicly accessible CVS repository, you could add support for your favorite language. If your interested, e-mail me and I can get you going. (Note:: You must be logged into SourceForge to use this e-mail service. That means you must be a SourceForge member - which you would have to be in order to work on any SourceForge project.)

Why doesn't SMC follow the Harel/UML statechart specification?
Does SMC use hierarchical state machines?
Does SMC support concurrent states?

SMC's finite state machine approach begins with an active object. An active object receives asynchronous events and may send such events as well. The finite state machine is used to put asynchronous events in context just as a call stack is used to maintain context for synchronous programming. SMC's goal is to provide FSM support for an application's active objects. Thus the SMC-generated FSM is skeletal. The object is responsible for defining the guard conditions, entry, exit and transition actions and maintaining the member data. The focus is on developing the application object. The FSM provides only a thin layer for maintaining aysnchronous context.

SMC state machine allows an active object to be in one state at a time. Concurrent states are not supported. One way to implement concurrent states is to create a subordinate object with its own associated finite state machine. So now both the parent and child objects have their own FSM operating concurrently.

When I begain working on SMC, my experience up to then had been with formal Finite State Machines (FSM), Push-down FSM and with something called an Augmented Transition Network (ATN) which is an FSM on steriods. ATNs were used in Natural Language Processing to parse text (used mostly in the 1970s).

ATNs have transition guards, push/pop transitions, default transitions and backtracking (rewind state transitions to an earlier time and try a different transition - needed in parsing text but not possible in event-driven software unless you have a time machine.) If your are familiar with ATNs, you can see where SMC came from.

I have tried to use UML syntax whereever possible. But there is no getting around that my philosophy about state machines is distinct from the Harel/UML philosophy. The following list shows whether a UML statechart feature is supported by SMC or not.

In summary, SMC is not and will never will be a Statechart implementation. The SMC and Statechart philosophies are too different to be reconciled.

How are SMC state machines persisted?

As of version 2.2.0, SMC now supports persistance via the "-serial" command line switch. See SMC Programmer's Manual for a detailed explanation on persisting FSMs. This section has sample code for persisting to a flat file in C++, Java, [incr Tcl], VB.net and C#.

How can I be informed about when an FSM changes state?

Release 5.0.1 supports asynchronous state change notification for Java only. See SMC Programmer's Manual for a detailed explanation on haw to receive state change notification.

This feature will be supported in C# and VB.net in the next release, using the .Net event delegation. There are no plans to support this feature for any other target language.

How much overhead does SMC add to an application?

Memory: There is exactly one object for each state. These state objects are instantiated at application start.

CPU: When you call a transtion method, that method calls the current state's equivalent transition method. The state transition method performs the action method calls.

Summary: Memory overhead matches the number of concrete states. CPU overhead is one subroutine call per transition. In short, overhead is negligible.

Can you fix SMC's code generators so they produce clean code?

Only if the fix is easy to implement. Remember:

  1. SMC is not a compiler but a glorified macro generator.
  2. Macro generators do not perform target code optimization or analysis.
  3. Which means SMC produces compilable code that may contain warnings or fail strict code analysis.

Example: SMC generates C++ code always contains the context parameter in the transition method. But if context is not used in the method body, then C++ compilers may output a warning due to the context parameter being specified but not used. The solution is to drop the name context from the parameter list.

But this is easier said than done. It requires a sophisticated code analysis to decide if a parameter is accessed within a method body. To do it right, SMC needs to generate a source code model from the FSM model, optimize the source code model and then generate the target code from the source code model. Is stringently clean code worth this effort? Unless I hear overwhelmingly to the contrary, my response is no.


Writing SMC Finite State Machines Questions

How do I automatically put #define/#include/package/import/package require statements into the generated code?

If you want SMC-generated code to be placed into a particular Java package/C++ namespace/Tcl namespace, then use the %package keyword: %package <package name>. See SMC Programmer's Manual for a detailed explanation in using the %package keyword.

If you want SMC-generated code to import a C++ namespace/Java class/Tcl package/VB.net/C# namespace, then use the %import keyword: %import <name>. See SMC Programmer's Manual for a detailed explanation in using the %import keyword.

If you want SMC-generated C++ code to include a header file, then use the %include keyword: %include <sys/time.h> or %include "AppTimer.h". These files and the %header file appear in the same order in the target <context>_sm.cpp file as in the .sm file. If you do not place either <> or "" around the header file, then SMC uses "" by default.

As for C++ #define macros, put these statements and all other code you want to appear verbatim in the generated code in a %{ ... %} block at your .sm file's beginning. See SMC Programmer's Manual for example code using the %{ ... %} block.

Note: The %{ ... %} block may only appear once in a .sm file and must be at the file's beginning before any other SMC construct. Comments may proceed this block however.

Note: For SMC-generated C++ code, the verbatim block is placed at the top of the .cpp file and not in the .h.

Why do I have to declare state machine actions as public?

The reason why the state machine actions in your application class have to be public because that is the only way the state classes will be able to access them.

You can make each state your application class' friend but that will be tedious. Since friendship is not inherited, you have to make every state a friend. Every time you add, delete or rename a state, you will have to update your application class as well.

I understand your frustration, but the simple access scheme used in C++ and iTcl doesn't allow for a more sophisticated access capability.

Note: In Java, you can give your state machine actions package-level access as long as your application class and the SMC-generated code are in the same Java package (see this FAQ answer to see how this is done.)

Why can't I issue a transition from within an action?

In case you believe this is a flaw in SMC, let me try to explain why this is so. A transition means an object has left one state and will be entering another. While in the transition, an object is not in any state. Actions occur while the object is in transition between states. How can a transition be issued when an object is not in any state? It makes no sense. I can't apply the transition to the previous state because the object has already left that state. I can't apply the transition to the next state because the object isn't there yet.

Is there any way to issue a transition from inside an action?

There is a simple solution to this problem. Let me restate the question differently:

I need to take a different transition depending on an action's result. How can I do this?

If this is your question, then the solution is to place the action in the guard. That way your FSM executes the transition associated with the action result. For example, your context class has an method int startTask(Task t) which returns an integer value zero, 1 or 2 corresponding to the task starting successfully, task suspended and task start failed. You want to take a different transition for each result. There is also a method int getLatestResult() which returns the latest startWork(Task t) result. The .sm code to accomplish this is:

Idle { ProcessTask(t: Task) [ctxt.startWork(t) == 0] Working {} ProcessTask(t: Task) [ctxt.getLatestResult() == 1] Suspended {} // Note: since startWork() returns 0, 1 or 2, we know what // result code is not 0 or 1. So no guard is needed. ProcessTask(t: Task) Failed {} }

If this technique does not work for you, then you could place the action in a state's Entry action list and have the action issue the transition from there. In this one case, actions may issue transitions because the current state is now set. I do not encourage this technique because it can cause more problems then solve. If you do use it, then make sure the transition is issued by the last entry action and have that action issue the transtion immediately prior to returning. In short, the transition is the very last statement executed by all the entry actions.

If transition guards and entry actions do not answer, then read the SMC programmer's manual which shows how actions can issue transitions by using timers and transition queues.

Is SMC-generated code thread safe?

The -sync command line option used with -java and -vb causes SMC to add the synchronized keyword (Java), SyncLock Me/End SyncLock (VB.net) or lock(this){...} (C#) to the transition methods. Therefore, if a transition has been issued from one thread and a second thread attempts to issue a transition before the first thread's transition has been completed, then the second thread will be blocked until the current transition returns.

There are no plans to generate thread-safe Tcl code. It is up to the developer to guarantee that two separate threads cannot issue overlapping transitions.

Why doesn't SMC generate thread-safe C++ code?

Because the generated code is OS-dependent. I am unwilling to add such code and testing complexity to SMC by having SMC generate code based on both the target language and the target OS.

Why won't SMC accept my "if" statement?

Because "if" statements are not part of the SMC language but the target programming language. SMC is deliberately simple so it can support multiple target languages. The conditional statement must be moved into a context class method where the target language can handle it.

When more than one transition pushes to the same state, how can I handle the pop transitions differently?

The problem is this:

Idle { DoOneThing push(DoTask) {} DoAnyThing push(DoTask) {} // Popped transitions - may only be defined once but // two are needed. TaskDone Done {} TaskFailed Failed {} }

You want to handle the TaskDone transition differently when the push came from the DoOneThing transition than from DoAnyThing transition. In pre-v. 1.3.2 releases, there is no way to resolve this problem. Read this manual section to learn how v. 1.3.2 solves this problem.

How do I receive a callback when my state machine transitions to a new state?

If you are using a .Net language (C# or VB.Net), then you can hook into the FSM's StateChanged event:

public class AppClass { // The FSM context class. private AppContext fsm; public AppClass() { this.fsm = new AppContext(this); this.fsm.StateChanged += new EventHandler(this.ProcessEvent); } private void ProcessEvent(object sender, EventArgs args) { ... // Process event, retrieve state, forward it, etc. ... return; } }

There is currently no equivalent code in the other supported languages. You can implement the Observer pattern yourself since you always know when a state change has occurred:

  1. Your application code is responsible for issuing transitions by calling the appropriate transition method.
  2. The transition method does not return until the transition has completed and entered the new state.
  3. Therefore, your application knows when the FSM has entered a new state: the transition method has returned. It is at this point that you can issue a callback to registered state change observers.

Java's bean package could be used to implement state change events.

If your goal to execute certain actions when your FSM exits or enters a state, then see the Programmer's Manual section on Entry and Exit Actions.

Can a transition return a value?

No. Transitions are implemented as methods and called-for-effect only. If a transition's actions produce data which you need to access later, then you must store that data somewhere, probably in the FSM's associated context class.

Can a transition action throw an exception?

It is a bad idea to have a transition action deliberately throw an exception. Consider the following FSM:

Idle { Start(task: Task) Running { startTask(task); setStopTimer(task); } } Running { TaskDone(task: Task) Idle {} Timeout(timer: TimerTask, task: Task) Idle { stopTask(task); } }

A task is given only some much time to run and if it fails to complete in the allotted time, it is stopped. If the action startTask(task) throws an exception and the task is never started, then action setStopTimer(task) will never be called. That may be what you want but the FSM still ends up in the Running state which is not what you want. The FSM will now wait forever for a non-existent task to complete or a non-existent timer to expire.

A better solution is:

Idle { Start(task: Task) [ctxt.startTask(task) == true] Running { setStopTimer(task); } Start(task: Task) nil { // Error recovery actions here. } } Running { TaskDone(task: Task) Idle {} Timeout(timer: TimerTask, task: Task) Idle { stopTask(task); } }

startTask(task) returns true if the task successfully starts. Only then is the timer started and the FSM goes to the Running state. If the task fails to start, your FSM can perform error recovery and stay in the Idle state.

Note: as of v. 2.0.2, SMC-generated C++, Java and Tcl code is protected against action-thrown exceptions. If an exception is thrown, SMC makes certain that the FSM's current state is set before allowing the exception to pass on through. In Java, this is done using the finally keyword. If C++, the catch (...) construct is used along with throw; to rethrow the caught exception. In Tcl catch is used and the exception is rethrown with error.

But I really need to throw an exception!

One work-around is to have a transition action create an exception and have the application class throw it when the transition method has returned. In Java it would work this way:

  1. In your application class, add the data member:
    private Throwable _throwObj;
    Then add the transition action method:
    void setThrowable(Throwable t) { _throwObj = t; }
  2. If a transition detects the need to throw an exception, then it calls setThrowable and passes to it the appropriate exception object.
  3. When your application class issues a transition it does the following:
    _throwObj = null; _fsm.Dowork(); if (_throwObj != null) { throw (_throwObj); }

(Java only) Using this technique you can throw both runtime and checked exceptions. You can only throw runtime exceptions from a transition action because a Java method must explicitly declare the checked exceptions it throws and the generate transition methods cannot make such declarations.

How do I access the previous state inside a transition action?

When a transition starts, the current state is cleared and getState() returns NULL. However, previous state is not gone. It can be retrieved by calling getPreviousState().

How do I get SMC to generate a call-by-reference?

Because Tcl is a weakly-typed language, SMC does not require you to specify a transition argument's type. But SMC supports two Tcl "types": "value" and "reference". If a parameter's type is "value", then SMC will pass the parameter using call-by-value by prepending a "$" to the parameter name. If the type is "reference", then SMC will pass the parameter using call-by-reference and passing only the parameter name.

If no type is specified, then SMC defaults to call-by-value.

Why won't SMC accept class template instances?

Because it does not make programming sense. Consider the following:

  1. %class expects a class name after it and not a template. AppTemplate<int> is an actual class while AppTemplate<class T> is not a class - it is a template for a class.
  2. The code for AppTemplate<int> is in AppTemplate<class T>. By instantiating the class template, you are reusing previously written code. You cannot add code to a class template.
  3. This means that all the FSM-related code must already be in AppTemplate<class T>. If the class template knows nothing about SMC-generated classes, then making AppTemplate<int> the context class is a waste of time. There is no application code calling the SMC-generated code.

The solution to this problem is based on your owning the AppTemplate<class T> code. Create another classAppTemplateFSM, make it a data member in AppTemplate<class T> and also the context class for the FSM. All class template instances will then access the SMC-generated classes through AppTemplateFSM and SMC-generated classes access the template class methods through AppTemplateFSM. In short, AppTemplateFSM is doing exactly the same work as the SMC-generated context class: redirecting method calls between application code and SMC-generated code.

Now, if you want to use a templatized-FSM to go along with your class template, then good luck! Break out your Perl to read in the .sm template file and replace all the variable <T> class names with the target class names and then have SMC compile the result. As for me, I will not be supporting FSM templates.

Can I add arguments to a pop transition?

Yes you can. As the Programmer's Manual states, this feature was added in version 1.2.0. You can code up your pop transition as follows:

pop(FAILED, errorCode, reason)

and have then define the FAILED transition accepting those arguments:

FAILED(errorCode: int, reason: String) Idle { Abend(errorCode, reason); }

Why do I have to specify a transition argument's type when I am generating Python code?

Because I do not want to condition SMC's syntax on the target language. SMC's syntax is the same no matter which language you are using.

How do I set the context class' access level?

The "%access" keyword access a target language-specific class access level.

%access internal

This level is read in verbatim and used to set the context class' access level in Java and C#. The other target languages ignore this setting because they do not support class accessibility.

If you specify %access package when generating Java, this will be converted to /* package */ in the generated Java code because Java views no access level to mean package-level access. The reason for this is due to Java using the package keyword to specify the package name.

How can I determine which transitions are defined in the current state?

By compiling your .sm file with the -reflect option (note: only supported by -csharp, -java, -tcl and -vb). This causes either a getTransitions() method (Java, Tcl) or Transitions property (C#, VB.Net) to be generated for the state classes. This method returns a java.util.Map, System.Collections.IDictionary or Tcl array which maps transition names to an integer value:

The returned map contains an entry for all transitions.

To figure out the current transition's supported transitions, use the following code:

Map transitions = _fsm.getState().getTransitions();

See the Programmer's Manual to learn more.

How can I get SMC to generate event registration and event listening code?

SMC does not generate such code because that rightfully belongs in your application code. The idea is that your application receives these events from whatever event system and those events are then passed to your FSM.

The FSM's role is to remember what your object's state after the last received event. There is a natural and strong relationship between finite state machines and event-driven programming. The problem is that there are multiple places to register for events: GUIs, timers, messaging systems, etc. And for each there is a different API for each programming language. While I would love to have SMC generate such code, it simply is not feasible. For now you have to write the event system interface and pass the events to the FSM.

Why doesn't SMC accept the action object().name()?

The reason object().name() does not work is due to SMC generating code for multiple languages. This requirement forces me to use the simplest syntax for the transition and entry/exit actions. All programming languages support the construct "method(args)".

But the construct object().name() is not easily translated to any language. Because SMC does not directly translate the FSM code to one language, I am forced to use an overly simple FSM language.

Why does the transition action System.out.println("My output") result in invalid generated code?

No, this is not a bug. The answer to this question is the same as the previous question. Transition actions must be context class methods. This limitation makes it possible for SMC to correctly generate the target language code for multiple target programming languages. This forces you to wrap all code in context class methods. If this seems an inefficient burden, that is the price you pay for using SMC. SMC generates the myriad of tiny State Pattern classes for you. This allows you to write sophisticated finite state machines, leveraging the power of the State Pattern without the pattern's class explosiion overhead.

The price you pay is placing all code in your context class methods. You want to write output to the console? Has to be done via a context class method. Want to make an API call? Has to be done in a context class method. Don't like this limitation? Write the State Pattern classes yourself.

As the previous question states, SMC supports multiple target programming languages and so must use the lowest common programming language constructs to work. This means you have to hide your target language's complexity in your context class methods.

Can I use #ifdef preprocessor statements in my .sm file?

Sure, but you are responsible for running the .sm file through the preprocessor before passing the results to SMC. SMC knows nothing about #ifdef statements and will report them as errors.

How do I call a static method from the transition actions body.

Just like any other method:

myNonstaticMethod(); myStaticMethod();

SMC's prepending the ctxt. before all method names does not break calling static methods. It is a valid way to call static methods.

How can I get SMC to place %include in the header file rather than the source file?

You can't and you don't have to. SMC honors your %header and %include ordering. Place the %include before the %header. You will also have to do this inclusion prior to including %header elsewhere in your code.

When my timer expires and I issue a transition, I sometime get a StateUndefinedException. Why?

Because your code isn't thread-safe. One thread is already in the middle when it is pre-empted by the timer thread. The timer thread then issues another transition but since you are already in transition, the StateUndefinedException.

You need to protect your transitions by either using the -sync option if you are using Java, C# or VB.net or add the necessary code yourself.

How can I specify that the FSM context class name overriding the default xxxContext name?

In your .sm file use the keyword %fsmclass followed by the desired FSM context class name. This works for all supported languages.


Compiling SMC Finite State Machines Question

I've modified a .sm but it's not recompiled when I build. How do I get SMC to automatically run?

If your using make to build C++, then add the following lines to your makefile:

%_sm.h _sm.cpp : %.sm java -jar <path to Smc.jar> -c++ $<

If your version of make does not support multiple prefixes on the same line, then split the line into two rules:

%_sm.h : %.sm java -jar <path to Smc.jar> -c++ $< _sm.cpp : %.sm java -jar <path to Smcb.jar> -c++ $<

If your using make to build Java, then add these lines to your makefile:

%Context.java : %.sm java -jar <path to Smc.jar> -java $<

If you are using ant, then add the following to your build.xml:

  1. Specify where the Smc.jar file is located:
    <property name="bin.dir" location="path to Smc.jar" /> <property name="smc.jar" location="${bin.dir}/Smc.jar" />
  2. Specify where .sm files are located:
    <property name="etc.dir" location="etc" /> <property name="sm.file" location="${etc.dir}/filename.sm" />
  3. Specify how the target language file is generated:
    <target name="gen" description="Compile .sm file" depends="init"> <java dir="${src.dir}" jar="${smc.jar}" classpathref="class.path" fork="true"> <arg line="-target language option [put SMC options here] -d ${src.dir} ${sm.file}"/> </java> </target>

If you are using Microsoft's Visual C++, then do the following:

  1. Open your project in VC++.
  2. Add the .sm file or files to the project.
  3. For each .sm file, right click on the file and select the "Settings..." item from the pop-up menu.
  4. In the "Project Settings" dialog, select the "Custom Build" tab.
  5. Click in the "Build Command(s)" text box and enter: "java -jar <path to Smc.jar> -c++ ${InputPath}".
  6. Click in the "Output file(s)" text area and enter: "$(InputName)_sm.h $(InputName)_sm.cpp".
  7. Click on the dialog box's "OK" button.

If you are using VB.Net or C# in Visual Studio, then there is no solution currently. When you select your .sm file and look at the properties, there is a "Custom Tool" property. What you enter here is the name of a registered custom tool. The registered custom tools can be found in the registry key:
HKLM\Software\Microsoft\VisualStudio\7.[01]\Generators

These generators are COM objects implementing the IVsSingleFileGenerator interface. This interface is given the file name to be custom compiled and returns a byte array containing the compilation. An SMC custom tool would:

  1. Fork off a Java process to do the actual compilation.
  2. Read the compiled _sm.cs file into the byte array and return that.

Well, no such custom tool exists. I have no experience writing COM objects nor hooking them into Visual Studio. I am not even sure if it could work given that the compilation must be done in a separate process.

Why does SMC throw any ArrayIndexOutOfBoundsException when I compile my .sm file?

Because your are using an SMC version < 3.0.0 and your .sm file contains unicode characters. SMC v. 3.0.0 and beyond is now able to handle unicode.

How can I get rid of all exception-handling code?

Firstly, "-noex" tells SMC not to initiate an exception throw. SMC still generates the try/catch/rethrow blocks to protect the FSM against application-thrown exceptions. If SMC didn't generate this code, an application exception would leave the FSM's state unset and that means your FSM would stop functioning.

If you application code does not throw exceptions, the SMC-generated try/catch/rethrow blocks are not needed. Use the "-nocatch" command line option to prevent try/catch/rethrow generation.

Note: If your application uses exceptions (especially if you are generating Java code), using "-nocatch" is strongly discouraged.

How can I tell SMC which C++ cast operator to use?

Use the "-cast <cast_operator>" command line option. The allowed C++ cast operators are dynamic_cast (default), static_cast and reinterpret_cast.

How can I tell SMC where to put the generated files?

Use the "-d <directory>" command line option. The directory must be accessible from the current working directory and writeable.

How can I tell SMC not to exit?

Use SMC's "-return" command line option.

Why is getState() method/State property in the generated Context class and not in FSMContext?

If placed in FSMContext, it would have to return a vanilla State object which does nothing, forcing the need to downcast the reference to the generated State class. I chose not to place downcasts throughout the generated code but instead use one downcast in getState(). This getState() must be placed in the generated Context class and not in FSMContext.


Debugging SMC Finite State Machines Questions

How do I turn on state machine debugging?

  1. Use SMC's "-g" flag when compiling your state machine. Debugging output will be added to the generated code. Note: this debug output is not produced unless turned on at run time.
  2. Find where you instantiate your state machine context object and turn on debugging:
    • C++: _state_machine->setDebugFlag(true);
    • Java: _state_machine.setDebugFlag(true);
    • Tcl: $_state_machine setDebugFlag 1
    • VB.net: _state_machine.DebugFlag = True
    • C#: _state_machine.DebugFlag = True
    • Python: self._fsm.setDebugFlag(True)
  3. The debug output is currently sent to standard error (System.err in Java). This can be changed programatically:
    • C++: _state_machine->setDebugStream(ostream&);
    • Java: _state_machine.setDebugStream(java.io.PrintStream);
    • Tcl: $_state_machine setDebugStream %channelId%;
    • VB.net: _state_machine.DebugStream = <System.IO.TextWriter object>
    • C#: _state_machine.DebugStream = <System.IO.TextWriter object>
    • Python: self._state_machine.setDebugStream(stream)

How do I use something other than C++ iostreams?

Use the -nostreams option to replace iostreams with the output mechanism of your choice.


Displaying SMC Finite State Machines Questions

How can I graphically display an FSM?

SMC v. 3.2.0 now generates Graphviz DOT files with the -graph option. There is a -glevel int option specifying how much FSM detail to place in the DOT file: level 0 gives you least and level 2 the most. View the gallery for more information and images of the SMC-generated DOT files using all three levels.

There is also the -table target. SMC generates an HTML table listing the actions for each state/transition pair. Each state's entry and exit actions are listed. The table is not as simple as it first seems because transition guards can make the generated HTML large and unreadable.

Since -table and -graph are targets like -c++, -java, etc., you may not use it in conjunction with other targets.

Why write state machines in text and then compile them? Why not create a GUI to draw state machines?

Because you are already using a text editor to write your C++/Java/Tcl/VB.net/C#/etc. code. The write/compile/test loop is well supported by today's IDEs and fitting SMC into that loop is easy. Fitting in a GUI is not so easy.

Then there is the issue of developing a GUI that runs on multiple platforms which is difficult even when using Java Swing. Because SMC is a command line application whose only OS interaction is reading and writing files, I am highly confident that Smc.jar will run on any Java-supported platform. But porting a GUI application would be a time consuming process - time I don't have.

Another philosophical argument against a GUI is that you spend more time trying to make the FSM drawing look nice than on actual development. Laying out the states and routing the transitions so that the drawing is somewhat readable is a time-consuming nuisance with little value.

Besides, my GUI experience is limited.

Why does SMC place only the fully-qualified <map name>::<state name> in the Graphviz DOT file? Why not just the state name?

See the Programmer's Manual for a detailed explanation. Graphviz uses a global namespace for node names and so SMC must use the fully-qualified state name as the node name to avoid confusing Graphviz. Otherwise Graphviz would view MainMap::Start and ConnectMap::Start as being the same node (Start) and mess up the links.