Browse Source

Erlang examples from EUC 2015

Stepan Mitkin 4 years ago
parent
commit
915bea0354
32 changed files with 1633 additions and 366 deletions
  1. 2 0
      .gitignore
  2. 3 3
      DRAKONEditor/DRAKONEditor-Info.plist
  3. 9 6
      DRAKONEditor/DRAKONEditor.xcodeproj/project.pbxproj
  4. 7 0
      DRAKONEditor/DRAKONEditor.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  5. 41 0
      DRAKONEditor/DRAKONEditor.xcodeproj/project.xcworkspace/xcshareddata/DRAKONEditor.xccheckout
  6. BIN
      DRAKONEditor/DRAKONEditor.xcodeproj/project.xcworkspace/xcuserdata/stipan.xcuserdatad/UserInterfaceState.xcuserstate
  7. 10 0
      DRAKONEditor/DRAKONEditor.xcodeproj/project.xcworkspace/xcuserdata/stipan.xcuserdatad/WorkspaceSettings.xcsettings
  8. 88 0
      DRAKONEditor/DRAKONEditor.xcodeproj/xcuserdata/stipan.xcuserdatad/xcschemes/DRAKONEditor.xcscheme
  9. 22 0
      DRAKONEditor/DRAKONEditor.xcodeproj/xcuserdata/stipan.xcuserdatad/xcschemes/xcschememanagement.plist
  10. BIN
      examples/Erlang/basic/basic.drn
  11. 491 0
      examples/Erlang/basic/basic.erl
  12. 9 0
      examples/Erlang/basic/readme.txt
  13. BIN
      examples/Erlang/erldemo.drn
  14. 0 218
      examples/Erlang/erldemo.erl
  15. BIN
      examples/Erlang/fsm/code_door.drn
  16. 187 0
      examples/Erlang/fsm/code_door.erl
  17. 66 0
      examples/Erlang/fsm/fsm_demo.erl
  18. BIN
      examples/Erlang/fsm/lexer.drn
  19. 335 0
      examples/Erlang/fsm/lexer.erl
  20. 38 0
      examples/Erlang/fsm/readme.txt
  21. BIN
      examples/Erlang/gen_server/musician.drn
  22. 181 0
      examples/Erlang/gen_server/musician.erl
  23. 9 0
      examples/Erlang/gen_server/readme.txt
  24. 0 9
      examples/Erlang/readme.txt
  25. 0 130
      examples/Erlang/sel2.erl
  26. 18 0
      examples/Erlang/supervision/de_sup.erl
  27. 65 0
      examples/Erlang/supervision/readme.txt
  28. 17 0
      examples/Erlang/supervision/session_root_sup.erl
  29. 15 0
      examples/Erlang/supervision/session_sup.erl
  30. BIN
      examples/Erlang/sel2.drn
  31. 5 0
      examples/Erlang/supervision/super.erl
  32. 15 0
      examples/Erlang/supervision/ybed_sup.erl

+ 2 - 0
.gitignore

@@ -8,3 +8,5 @@ tmp/fail
 tmp/good
 
 tmp/no_version
+
+*.beam

+ 3 - 3
DRAKONEditor/DRAKONEditor-Info.plist

@@ -4,6 +4,8 @@
 <dict>
 	<key>CFBundleDevelopmentRegion</key>
 	<string>English</string>
+	<key>CFBundleDisplayName</key>
+	<string>DRAKON Editor</string>
 	<key>CFBundleExecutable</key>
 	<string>${EXECUTABLE_NAME}</string>
 	<key>CFBundleIconFile</key>
@@ -17,9 +19,7 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>1.25</string>
-	<key>CFBundleDisplayName</key>
-	<string>DRAKON Editor</string>
+	<string>1.26</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleVersion</key>

+ 9 - 6
DRAKONEditor/DRAKONEditor.xcodeproj/project.pbxproj

@@ -3,7 +3,7 @@
 	archiveVersion = 1;
 	classes = {
 	};
-	objectVersion = 45;
+	objectVersion = 46;
 	objects = {
 
 /* Begin PBXBuildFile section */
@@ -148,8 +148,11 @@
 /* Begin PBXProject section */
 		29B97313FDCFA39411CA2CEA /* Project object */ = {
 			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0630;
+			};
 			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DRAKONEditor" */;
-			compatibilityVersion = "Xcode 3.1";
+			compatibilityVersion = "Xcode 3.2";
 			developmentRegion = English;
 			hasScannedForEncodings = 1;
 			knownRegions = (
@@ -217,6 +220,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				COMBINE_HIDPI_IMAGES = YES;
 				COPY_PHASE_STRIP = NO;
 				GCC_DYNAMIC_NO_PIC = NO;
 				GCC_ENABLE_FIX_AND_CONTINUE = YES;
@@ -234,6 +238,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				COMBINE_HIDPI_IMAGES = YES;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				GCC_MODEL_TUNING = G5;
 				GCC_PRECOMPILE_PREFIX_HEADER = YES;
@@ -247,26 +252,24 @@
 		C01FCF4F08A954540054247B /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				PREBINDING = NO;
-				SDKROOT = macosx10.6;
+				SDKROOT = macosx10.9;
 			};
 			name = Debug;
 		};
 		C01FCF5008A954540054247B /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
 				GCC_C_LANGUAGE_STANDARD = gnu99;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				PREBINDING = NO;
-				SDKROOT = macosx10.6;
+				SDKROOT = macosx10.9;
 			};
 			name = Release;
 		};

+ 7 - 0
DRAKONEditor/DRAKONEditor.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:">
+   </FileRef>
+</Workspace>

+ 41 - 0
DRAKONEditor/DRAKONEditor.xcodeproj/project.xcworkspace/xcshareddata/DRAKONEditor.xccheckout

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDESourceControlProjectFavoriteDictionaryKey</key>
+	<false/>
+	<key>IDESourceControlProjectIdentifier</key>
+	<string>E3A37D21-BB7D-43F7-8A7E-8F693251E3AC</string>
+	<key>IDESourceControlProjectName</key>
+	<string>DRAKONEditor</string>
+	<key>IDESourceControlProjectOriginsDictionary</key>
+	<dict>
+		<key>BEA571F181DF356B19B140BEBC78E4931AE2B9DE</key>
+		<string>https://github.com/stepan-mitkin/drakon_editor.git</string>
+	</dict>
+	<key>IDESourceControlProjectPath</key>
+	<string>DRAKONEditor/DRAKONEditor.xcodeproj</string>
+	<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
+	<dict>
+		<key>BEA571F181DF356B19B140BEBC78E4931AE2B9DE</key>
+		<string>../../..</string>
+	</dict>
+	<key>IDESourceControlProjectURL</key>
+	<string>https://github.com/stepan-mitkin/drakon_editor.git</string>
+	<key>IDESourceControlProjectVersion</key>
+	<integer>111</integer>
+	<key>IDESourceControlProjectWCCIdentifier</key>
+	<string>BEA571F181DF356B19B140BEBC78E4931AE2B9DE</string>
+	<key>IDESourceControlProjectWCConfigurations</key>
+	<array>
+		<dict>
+			<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
+			<string>public.vcs.git</string>
+			<key>IDESourceControlWCCIdentifierKey</key>
+			<string>BEA571F181DF356B19B140BEBC78E4931AE2B9DE</string>
+			<key>IDESourceControlWCCName</key>
+			<string>drakon_editor</string>
+		</dict>
+	</array>
+</dict>
+</plist>

BIN
DRAKONEditor/DRAKONEditor.xcodeproj/project.xcworkspace/xcuserdata/stipan.xcuserdatad/UserInterfaceState.xcuserstate


+ 10 - 0
DRAKONEditor/DRAKONEditor.xcodeproj/project.xcworkspace/xcuserdata/stipan.xcuserdatad/WorkspaceSettings.xcsettings

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>
+	<true/>
+	<key>SnapshotAutomaticallyBeforeSignificantChanges</key>
+	<true/>
+</dict>
+</plist>

+ 88 - 0
DRAKONEditor/DRAKONEditor.xcodeproj/xcuserdata/stipan.xcuserdatad/xcschemes/DRAKONEditor.xcscheme

@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0630"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "8D1107260486CEB800E47090"
+               BuildableName = "DRAKONEditor.app"
+               BlueprintName = "DRAKONEditor"
+               ReferencedContainer = "container:DRAKONEditor.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <Testables>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "8D1107260486CEB800E47090"
+            BuildableName = "DRAKONEditor.app"
+            BlueprintName = "DRAKONEditor"
+            ReferencedContainer = "container:DRAKONEditor.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Debug"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "8D1107260486CEB800E47090"
+            BuildableName = "DRAKONEditor.app"
+            BlueprintName = "DRAKONEditor"
+            ReferencedContainer = "container:DRAKONEditor.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      buildConfiguration = "Release"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "8D1107260486CEB800E47090"
+            BuildableName = "DRAKONEditor.app"
+            BlueprintName = "DRAKONEditor"
+            ReferencedContainer = "container:DRAKONEditor.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 22 - 0
DRAKONEditor/DRAKONEditor.xcodeproj/xcuserdata/stipan.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>DRAKONEditor.xcscheme</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>0</integer>
+		</dict>
+	</dict>
+	<key>SuppressBuildableAutocreation</key>
+	<dict>
+		<key>8D1107260486CEB800E47090</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+	</dict>
+</dict>
+</plist>

BIN
examples/Erlang/basic/basic.drn


+ 491 - 0
examples/Erlang/basic/basic.erl

@@ -0,0 +1,491 @@
+% Autogenerated with DRAKON Editor 1.26
+
+-module(basic).
+-export([create_user/3, echo/0, echo_t/0, future_time/1, hello/2, log_on/2, number_to_word/1, print_result/1, quad_equation/3, quicksort/2, run/0, split/2, split_core/3]).
+%  stipan.mitkin@gmail.com
+%  http://drakon-editor.sourceforge.net/
+
+%  Copyright 2015 Stepan Mitkin
+%  This code is PUBLIC DOMAIN.
+
+access_denied(User) ->
+    % item 255
+    {user, Name, _, _, _} = User,
+    % item 256
+    io:format("Access denied to user ~s.~n", [Name])
+.
+
+add_buffer(Buffer, List) ->
+    % item 486
+    Reversed = lists:reverse(Buffer),
+    [Reversed | List]
+.
+
+attach_session(User) ->
+    % item 248
+    {user, Name, _, _, _} = User,
+    % item 249
+    io:format("User ~s has logged on.~n", [Name])
+.
+
+check_password(User, Password) ->
+    % item 239
+    {user, _, Salt, Hash, Enabled} = User,
+    % item 236
+    case Enabled of true -> 
+        % item 240
+        ActualHash = make_pass_hash(Salt, Password),
+        % item 241
+        ActualHash == Hash
+    ; false ->
+        % item 242
+        false
+    end
+.
+
+create_user(Name, Password, Enabled) ->
+    % item 222
+    Salt = crypto:rand_bytes(8),
+    % item 223
+    Hash = make_pass_hash(Salt, Password),
+    % item 221
+    User = {
+    	user,
+    	Name,
+    	Salt,
+    	Hash,
+    	Enabled
+    },
+    % item 305
+    User
+.
+
+echo() ->
+    % item 541
+    io:format(
+     "echo: waiting...~n", []
+    ),
+    receive
+        stop ->
+            % item 542
+            io:format("stopping~n", []),
+            % item 531
+            ok
+        ;
+        {msg, Message} ->
+            % item 532
+            io:format("~p~n", [Message]),
+            % item 536
+            echo()
+        ;
+       _ ->
+            % item 539
+            io:format("unknown~n", []),
+            % item 536
+            echo()
+    end
+.
+
+echo_t() ->
+    % item 561
+    io:format(
+     "echo_t: waiting...~n", []
+    ),
+    receive
+        stop ->
+            % item 562
+            io:format(
+             "stopping~n", []
+            ),
+            % item 553
+            ok
+        ;
+        {msg, Message} ->
+            % item 554
+            io:format(
+             "~p~n", [Message]
+            ),
+            % item 556
+            echo_t()
+        ;
+        _ ->
+            % item 559
+            io:format(
+             "unknown~n",
+             []
+            ),
+            % item 556
+            echo_t()
+        
+        after 10000 ->
+            % item 565
+            io:format(
+             "exit by timeout~n",
+             []
+            ),
+            % item 567
+            ok
+    end
+.
+
+future_time(Seconds) ->
+    % item 295
+    Now = calendar:local_time(),
+    NowSec = calendar:datetime_to_gregorian_seconds(Now),
+    % item 296
+    ExpSec = NowSec + Seconds,
+    % item 297
+    calendar:gregorian_seconds_to_datetime(ExpSec)
+.
+
+hello(FirstName, LastName) ->
+    % item 203
+    io:format(
+      "Hello, ~s ~s~n",
+      [FirstName, LastName]
+    )
+.
+
+hi() ->
+    % item 304
+    io:format("hi~n", [])
+.
+
+log_on(User, Password) ->
+    % item 287
+    case check_password(User, Password) of true -> 
+        % item 290
+        attach_session(User)
+    ; false ->
+        % item 291
+        access_denied(User)
+    end
+.
+
+make_pass_hash(Salt, Password) ->
+    % item 229
+    PassBinary = unicode:characters_to_binary(
+    	Password,
+    	utf8
+    ),
+    ToHash = [Salt, PassBinary],
+    % item 230
+    crypto:hash(sha512, ToHash)
+.
+
+number_to_word(Number) ->
+    case Number of
+        0 ->
+            % item 321
+            "zero"
+        ;
+        1 ->
+            % item 322
+            "one"
+        ;
+        2 ->
+            % item 323
+            "two"
+        ;
+       _ ->
+            % item 324
+            "many"
+    end
+.
+
+print_result(Result) ->
+    case Result of
+        ok ->
+            % item 338
+            io:format(
+              "it's okay~n",
+              []
+            )
+        ;
+        {error, Message} ->
+            % item 339
+            io:format(
+              "Error: ~s~n",
+              [Message]
+            )
+        ;
+       _ ->
+            % item 340
+            io:format(
+              "Unknown: ~p~n",
+              [Result]
+            )
+    end
+.
+
+quad_equation(A, B, C) ->
+    % item 275
+    case A == 0 of true -> 
+        % item 278
+        {error, not_quad}
+    ; false ->
+        % item 262
+        Dis = B * B - 4 * A * C,
+        A2 = 2 * A,
+        % item 268
+        case Dis > 0 of true -> 
+            % item 279
+            SqDis = math:sqrt(Dis),
+            % item 271
+            X1 = (-B + SqDis) / A2,
+            % item 272
+            X2 = (-B - SqDis) / A2,
+            % item 273
+            {ok, X1, X2}
+        ; false ->
+            % item 263
+            case Dis == 0 of true -> 
+                % item 266
+                X1 = -B / A2,
+                % item 267
+                X2 = X1,
+                % item 273
+                {ok, X1, X2}
+            ; false ->
+                % item 274
+                {error, no_roots}
+            end
+        end
+    end
+.
+
+quicksort(List, Comparer) ->
+    % item 578
+    case List =:= [] of true -> 
+        % item 379
+        Result = List
+    ; false ->
+        % item 373
+        [ Pivot | Others ] = List,
+        % item 386
+        LessThanPivot = fun(X) ->
+        	Comparer(X, Pivot) < 0 
+        end,
+        % item 385
+        {Left, Right} = lists:partition(
+        	LessThanPivot,
+        	Others
+        ),
+        % item 378
+        LeftSorted = quicksort(Left, Comparer),
+        RightSorted = quicksort(Right, Comparer),
+        % item 383
+        Result = LeftSorted ++ [Pivot] ++ RightSorted
+    end,
+    % item 384
+    Result
+.
+
+run() ->
+    % item 419
+    hi(),
+    % item 420
+    hello("Joe", "Black"),
+    % item 421
+    io:format(
+      "~p~n",
+      [future_time(0)]
+    ),
+    % item 422
+    io:format(
+      "~p~n",
+      [future_time(60)]
+    ),
+    % item 423
+    io:format(
+      "~p~n",
+      [future_time(3600)]
+    ),
+    % item 424
+    User = create_user(
+    	"Bender",
+    	"Erlang123",
+    	true
+    ),
+    % item 425
+    log_on(User, "111"),
+    % item 426
+    log_on(User, "Erlang123"),
+    % item 427
+    io:format(
+      "Solving quadratic: ~p~n",
+      [quad_equation(1, -8, 12)]
+    ),
+    % item 428
+    io:format(
+      "Solving quadratic: ~p~n",
+      [quad_equation(5, 3, 7)]
+    ),
+    % item 429
+    io:format(
+      "Solving quadratic: ~p~n",
+      [quad_equation(1, -6, 9)]
+    ),
+    % item 430
+    io:format(
+      "Number to word: ~p~n",
+      [number_to_word(0)]
+    ),
+    % item 431
+    io:format(
+      "Number to word: ~p~n",
+      [number_to_word(1)]
+    ),
+    % item 432
+    io:format(
+      "Number to word: ~p~n",
+      [number_to_word(25)]
+    ),
+    % item 433
+    print_result(ok),
+    % item 434
+    print_result({error, "Division by 0"}),
+    % item 435
+    print_result(
+     "I am an unexpected string"
+    ),
+    % item 507
+    io:format(
+      "~p~n",
+      [split("one,two,three", $,)]
+    ),
+    % item 508
+    io:format(
+      "~p~n",
+      [split(",one,,,two,three,", $,)]
+    ),
+    % item 509
+    io:format(
+      "~p~n",
+      [split(",,,,", $,)]
+    ),
+    % item 510
+    io:format(
+      "~p~n",
+      [split("", $,)]
+    ),
+    % item 440
+    IntCmp = fun(X1, X2) ->
+    	X1 - X2
+    end,
+    % item 438
+    io:format(
+      "~p~n",
+      [quicksort([5, 5, 5, 5], IntCmp)]
+    ),
+    % item 441
+    io:format(
+      "~p~n",
+      [quicksort([], IntCmp)]
+    ),
+    % item 442
+    io:format(
+      "~p~n",
+      [quicksort([3], IntCmp)]
+    ),
+    % item 443
+    io:format(
+      "~p~n",
+      [quicksort([3, 1, 4, 2, 6, 8, 7, 5], IntCmp)]
+    ),
+    % item 572
+    Pid1 = spawn(fun echo/0),
+    % item 573
+    Pid1 ! {msg, "First message"},
+    % item 574
+    Pid1 ! {msg, "Second message"},
+    % item 577
+    Pid1 ! stop,
+    % item 575
+    Pid2 = spawn(fun echo_t/0),
+    % item 576
+    Pid2 ! {msg, "Good morning"},
+    % item 436
+    io:format("All done!")
+.
+
+split(List, Separator) ->
+    % item 457
+    Acc = {idle, [], []},
+    % item 458
+    {_, Output, Buffer} = split_core(
+    	List,
+    	Separator,
+    	Acc
+    ),
+    % item 512
+    case Buffer =:= [] of true -> 
+        % item 515
+        OutList = Output
+    ; false ->
+        % item 487
+        OutList = add_buffer(Buffer, Output)
+    end,
+    % item 464
+    lists:reverse(OutList)
+.
+
+split_core(List, Separator, Acc) ->
+    % item 511
+    {State, Output, Buffer} = Acc,
+    % item 465
+    case List =:= [] of true -> 
+        % item 468
+        Acc
+    ; false ->
+        % item 476
+        [Head | Rest] = List,
+        case State of
+            idle ->
+                % item 488
+                case Head =:= Separator of true -> 
+                    % item 499
+                    Acc2 = {idle, Output, Buffer}
+                ; false ->
+                    % item 491
+                    Buffer2 = [Head],
+                    % item 492
+                    Acc2 = {token, Output, Buffer2}
+                end,
+                % item 502
+                split_core(
+                	Rest,
+                	Separator,
+                	Acc2
+                )
+            ;
+            token ->
+                % item 495
+                case Head =:= Separator of true -> 
+                    % item 500
+                    Output2 = add_buffer(
+                      Buffer,
+                      Output
+                    ),
+                    % item 501
+                    Acc2 = {idle, Output2, []}
+                ; false ->
+                    % item 497
+                    Buffer2 = [Head | Buffer],
+                    % item 498
+                    Acc2 = {token, Output, Buffer2}
+                end,
+                % item 502
+                split_core(
+                	Rest,
+                	Separator,
+                	Acc2
+                )
+            ;
+            _ ->
+            throw("Unexpected switch value")
+        end
+    end
+.
+
+

+ 9 - 0
examples/Erlang/basic/readme.txt

@@ -0,0 +1,9 @@
+A basic demo for DRAKON-Erlang.
+
+How to run:
+1. Start Erlang shell.
+	erl
+2. Compile
+	c(basic).
+3. Run
+	basic:run().

BIN
examples/Erlang/erldemo.drn


+ 0 - 218
examples/Erlang/erldemo.erl

@@ -1,218 +0,0 @@
-% Autogenerated with DRAKON Editor 1.26
-
--module(erldemo).
--export([common_fate/1, fibonacci/1, foreach/2, main/0, quicksort/2]).
-
-back_cmp(X, Y) ->
-    % item 168
-    case X < Y of true -> 
-        % item 169
-        1
-    ; false ->
-        % item 173
-        case X > Y of true -> 
-            % item 174
-            -1
-        ; false ->
-            % item 175
-            0
-        end
-    end
-.
-
-common_fate(X) ->
-    % item 279
-    case X > 0 of true -> 
-        % item 282
-        Y = 500
-    ; false ->
-        % item 283
-        Y = 200
-    end,
-    % item 284
-    Y * 7
-.
-
-fibonacci(N) ->
-    case N of
-        0 ->
-            % item 218
-            [0]
-        ;
-        1 ->
-            % item 219
-            [1, 0]
-        ;
-       _ ->
-            % item 220
-            [First, Second | Rest] = fibonacci(N - 1),
-            % item 221
-            Fib = First + Second,
-            % item 222
-            [Fib, First, Second | Rest]
-    end
-.
-
-foreach(List, Visitor) ->
-    % item 55
-    case List == [] of true -> 
-        % item 56
-        void
-    ; false ->
-        % item 59
-        [ Head | Rest ] = List,
-        Visitor(Head),
-        % item 60
-        foreach(Rest, Visitor)
-    end
-.
-
-foreach_demo() ->
-    % item 49
-    io:format("iteration demo~n"),
-    % item 42
-    FibReversed = fibonacci(20),
-    Fibonacci = lists:reverse(FibReversed),
-    % item 224
-    Visitor = fun(X) -> 
-    	print(X)
-    end,
-    % item 61
-    foreach(Fibonacci, Visitor),
-    io:format("~n", [])
-.
-
-is_sorted(List) ->
-    % item 182
-    Length = length(List),
-    case Length of
-        0 ->
-            []
-        ;
-        1 ->
-            []
-        ;
-       _ ->
-            % item 191
-            [First, Second | Tail] = List,
-            % item 192
-            Cmp = back_cmp(First, Second),
-            % item 193
-            case Cmp == 1 of true -> 
-                % item 195
-                print_list(List),
-                throw("List not sorted")
-            ; false ->
-                % item 196
-                is_sorted(Tail)
-            end
-    end
-.
-
-main() ->
-    % item 34
-    foreach_demo(),
-    % item 66
-    quicksort_demo()
-.
-
-print(Item) ->
-    % item 48
-    io:format("~w ", [Item])
-.
-
-print_list(List) ->
-    % item 226
-    Visitor = fun(X) -> 
-    	io:format("~s ", [X]) 
-    end,
-    % item 225
-    foreach(List, Visitor),
-    % item 75
-    io:format("~n", [])
-.
-
-quicksort(List, Comparer) ->
-    % item 121
-    Length = length(List),
-    case Length of
-        0 ->
-            % item 157
-            Result = List,
-            % item 162
-            Result
-        ;
-        1 ->
-            % item 157
-            Result = List,
-            % item 162
-            Result
-        ;
-        2 ->
-            % item 158
-            [ First, Second | _ ] = List,
-            Cmp = Comparer(First, Second),
-            % item 159
-            case Cmp == -1 of true -> 
-                % item 160
-                Result = List
-            ; false ->
-                % item 138
-                Result = [Second, First]
-            end,
-            % item 162
-            Result
-        ;
-       _ ->
-            % item 141
-            [ Pivot | Others ] = List,
-            % item 223
-            LessThanPivot = fun(X) ->
-            	Comparer(X, Pivot) == -1 
-            end,
-            % item 198
-            {Left, Right} = lists:partition(
-            	LessThanPivot,
-            	Others
-            ),
-            % item 155
-            LeftSorted = quicksort(Left, Comparer),
-            RightSorted = quicksort(Right, Comparer),
-            % item 161
-            Result = LeftSorted ++ [Pivot] ++ RightSorted,
-            % item 162
-            Result
-    end
-.
-
-quicksort_demo() ->
-    % item 65
-    io:format("quick sort demo~n", []),
-    % item 67
-    Unsorted = [ "the", "sooner", "we", "start", "this", "the", "better" ],
-    Sorted   = [ "aa", "bb", "cc", "dd", "ee", "ff" ],
-    Reverse  = [ "ff", "ee", "dd", "cc", "bb", "aa" ],
-    Empty    = [],
-    Flat     = [ "flat", "flat", "flat", "flat", "flat" ],
-    % item 91
-    Comparer = fun(X, Y) -> back_cmp(X, Y) end,
-    Unsorted2 = quicksort(Unsorted, Comparer),
-    Sorted2 = quicksort(Sorted, Comparer),
-    Reverse2 = quicksort(Reverse, Comparer),
-    Empty2 = quicksort(Empty, Comparer),
-    Flat2 = quicksort(Flat, Comparer),
-    % item 68
-    print_list(Unsorted2),
-    print_list(Sorted2),
-    print_list(Reverse2),
-    print_list(Empty2),
-    print_list(Flat2),
-    % item 197
-    is_sorted(Unsorted2),
-    is_sorted(Sorted2),
-    is_sorted(Reverse2),
-    is_sorted(Empty2),
-    is_sorted(Flat2)
-.
-
-

BIN
examples/Erlang/fsm/code_door.drn


+ 187 - 0
examples/Erlang/fsm/code_door.erl

@@ -0,0 +1,187 @@
+% Autogenerated with DRAKON Editor 1.26
+
+-module(code_door).
+-behaviour(gen_fsm).
+-export([locked/2]).
+-export([open/2]).
+-export([opening/2]).
+-export([start_link/2]).
+-export([cancel/1, code_change/4, create/1, handle_event/3, handle_info/3, handle_sync_event/4, init/1, key/2, stop/1, terminate/3]).
+%  stipan.mitkin@gmail.com
+%  http://drakon-editor.sourceforge.net/
+
+%  Copyright 2015 Stepan Mitkin
+%  This code is PUBLIC DOMAIN.
+
+
+% The timeout between two button clicks - 10 sec.
+-define(TIMEOUT1, 5000).
+
+% The timeout while the door remains open - 30 sec.
+-define(TIMEOUT2, 10000).
+
+cancel(Name) ->
+    % item 107
+    gen_fsm:send_event(Name, cancel)
+.
+
+cancelled() ->
+    % item 82
+    io:fwrite("Cancel pressed.~n", [])
+.
+
+code_change(_OldVsn, StateName, StateData, _Extra) ->
+    % item 147
+    {ok, StateName, StateData}
+.
+
+create(Code) ->
+    % item 94
+    AlreadyTyped = [],
+    State = {AlreadyTyped, Code},
+    % item 95
+    Options = [],
+    % item 93
+    start_link(State, Options)
+.
+
+do_lock() ->
+    % item 78
+    io:fwrite("The door is locked.~n", [])
+.
+
+do_open() ->
+    % item 74
+    io:fwrite("The door is opened.~n", [])
+.
+
+handle_event(stop, _StateName, StateData) ->
+    % item 120
+    {stop, normal, StateData}
+.
+
+handle_info(_Info, StateName, StateData) ->
+    % item 153
+    {next_state, StateName, StateData}
+.
+
+handle_sync_event(_Event, _From, StateName, StateData) ->
+    % item 159
+    {next_state, StateName, StateData}
+.
+
+init(State) ->
+    % item 137
+    io:fwrite("init!~n", []),
+    % item 136
+    {ok, locked, State}
+.
+
+key(Name, Key) ->
+    % item 101
+    gen_fsm:send_event(Name, {button, Key})
+.
+
+report_key(Key) ->
+    % item 70
+    io:fwrite("key: ~s~n", [Key])
+.
+
+stop(Name) ->
+    % item 126
+    gen_fsm:send_all_state_event(Name, stop)
+.
+
+terminate(normal, _StateName, _StateData) ->
+    % item 114
+    io:fwrite("Code door: terminating.~n", []),
+    % item 113
+    ok
+.
+
+timeout_hit() ->
+    % item 86
+    io:fwrite("Timeout reached.~n", [])
+.
+locked(Message_, State) ->
+    case Message_ of
+    {button, Key} ->
+        % item 64
+        report_key(Key),
+        % item 49
+        {_, Code} = State,
+        % item 45
+        {next_state, opening, {Key, Code}, ?TIMEOUT1}
+    ;
+    _ ->
+        % item 46
+        {next_state, locked, State}
+    end
+.
+open(Message_, State) ->
+    case Message_ of
+    timeout ->
+        % item 61
+        timeout_hit(),
+        % item 62
+        do_lock(),
+        % item 53
+        {next_state, locked, State}
+    ;
+    dummy ->
+        % item 62
+        do_lock(),
+        % item 53
+        {next_state, locked, State}
+    ;
+    _ ->
+        % item 54
+        {next_state, open, State}
+    end
+.
+opening(Message_, State) ->
+    case Message_ of
+    {button, Key} ->
+        % item 63
+        report_key(Key),
+        % item 47
+        {SoFar, Code} = State,
+        Typed = SoFar ++ Key,
+        % item 41
+        case Typed =:= Code of true -> 
+            % item 57
+            do_open(),
+            % item 50
+            {next_state, open, {[], Code}, ?TIMEOUT2}
+        ; false ->
+            % item 48
+            {next_state, opening, {Typed, Code}, ?TIMEOUT1}
+        end
+    ;
+    cancel ->
+        % item 58
+        cancelled(),
+        % item 59
+        do_lock(),
+        % item 51
+        {next_state, locked, State}
+    ;
+    timeout ->
+        % item 60
+        timeout_hit(),
+        % item 59
+        do_lock(),
+        % item 51
+        {next_state, locked, State}
+    ;
+    _ ->
+        throw({invalid_state, "Message not supported by state 'opening'."})
+    end
+.
+
+
+start_link(State, Options) ->
+    gen_fsm:start_link(?MODULE, State, Options).
+
+
+

+ 66 - 0
examples/Erlang/fsm/fsm_demo.erl

@@ -0,0 +1,66 @@
+-module(fsm_demo).
+-export([run/0]).
+
+run() ->
+	standalone(),
+	fsm_based()
+.
+
+
+standalone() ->
+	io:fwrite("~n~n", []),
+	io:fwrite("standalone state machine test~n", []),
+	io:fwrite("=============================~n", []),	
+	Text = "var foo = bar.SomeMethod2(n + 10/x, c >= 10);",
+	Tokens = lexer:lex(Text),
+	
+	io:fwrite("Text: ~s~n", [Text]),
+	io:fwrite("Tokens:~n", []),
+	lists:foreach(
+		fun(Item) ->
+			{Type, TText} = Item,
+			io:fwrite("~w - ~s~n", [Type, TText])
+			end,
+		Tokens)
+.
+
+
+
+fsm_based() ->
+	io:fwrite("~n~n", []),
+	io:fwrite("gen_fsm state machine test~n", []),
+	io:fwrite("==========================~n", []),	
+	{ok, Door} = code_door:create("abc"),
+	
+	io:fwrite("~nTyping the code...~n", []),
+	timer:sleep(1000),	
+	code_door:key(Door, "a"),
+	timer:sleep(1000),
+	code_door:key(Door, "b"),
+	timer:sleep(1000),
+	code_door:key(Door, "c"),
+	timer:sleep(1000),
+	io:fwrite("Waiting, doing nothing...~n", []),		
+	timer:sleep(10000),
+
+
+	io:fwrite("~nTyping the code once more...~n", []),	
+	timer:sleep(1000),	
+	code_door:key(Door, "a"),
+	timer:sleep(1000),
+	code_door:key(Door, "b"),	
+	timer:sleep(1000),
+	io:fwrite("Waiting too long...~n", []),	
+	timer:sleep(6000),
+	
+	io:fwrite("~nTyping the code again...~n", []),	
+	timer:sleep(1000),	
+	code_door:key(Door, "a"),
+	timer:sleep(1000),
+	code_door:cancel(Door),
+	timer:sleep(1000),
+	
+	code_door:stop(Door),
+	
+	"Done!"
+.

BIN
examples/Erlang/fsm/lexer.drn


+ 335 - 0
examples/Erlang/fsm/lexer.erl

@@ -0,0 +1,335 @@
+% Autogenerated with DRAKON Editor 1.26
+
+-module(lexer).
+-export([create/1]).
+-export([send_event/2]).
+-export([get_state/1]).
+-export([get_data/1]).
+-export([lex/1]).
+%  stipan.mitkin@gmail.com
+%  http://drakon-editor.sourceforge.net/
+
+%  Copyright 2015 Stepan Mitkin
+%  This code is PUBLIC DOMAIN.
+
+add_char(State, Char) ->
+    % item 262
+    {Buffer, Tokens} = State,
+    % item 326
+    {[Char | Buffer], Tokens}
+.
+
+classify(Operators, Char) ->
+    % item 351
+    case Char =:= $_ of true -> 
+        % item 359
+        letter
+    ; false ->
+        % item 354
+        case (Char >= $0) andalso (Char =< $9) of true -> 
+            % item 369
+            digit
+        ; false ->
+            % item 370
+            case is_whitespace(Char) of true -> 
+                % item 365
+                whitespace
+            ; false ->
+                % item 361
+                case sets:is_element(Char, Operators) of true -> 
+                    % item 364
+                    operator
+                ; false ->
+                    % item 386
+                    letter
+                end
+            end
+        end
+    end
+.
+
+create_identifier(State) ->
+    % item 268
+    create_token(State, identifier)
+.
+
+create_number(State) ->
+    % item 329
+    create_token(State, number)
+.
+
+create_operator(State) ->
+    % item 330
+    create_token(State, operator)
+.
+
+create_operator_list() ->
+    % item 391
+    OperatorList = [
+    $!, 
+    $=, 
+    $<, 
+    $>, 
+    $-, 
+    $+, 
+    $/, 
+    $\\, 
+    $*, 
+    $%, 
+    $(, 
+    $), 
+    $[, 
+    $], 
+    ${, 
+    $}, 
+    $:, 
+    $., 
+    $;, 
+    $,, 
+    $^, 
+    $|, 
+    $&, 
+    $", 
+    $'],
+    % item 392
+    sets:from_list(OperatorList)
+.
+
+create_token(State, TokenType) ->
+    % item 327
+    {Buffer, Tokens} = State,
+    % item 274
+    case Buffer =:= [] of true -> 
+        % item 328
+        State
+    ; false ->
+        % item 277
+        Text = lists:reverse(Buffer),
+        Token = {TokenType, Text},
+        % item 278
+        {[], [Token | Tokens]}
+    end
+.
+
+is_long_operator(Text) ->
+    % item 338
+    case (((Text =:= "==") orelse (Text =:= "!=")) orelse (Text =:= "<=")) orelse (Text =:= ">=") of true -> 
+        % item 345
+        true
+    ; false ->
+        % item 344
+        false
+    end
+.
+
+is_whitespace(Char) ->
+    % item 378
+    case (((Char =:= 9) orelse (Char =:= 32)) orelse (Char =:= 13)) orelse (Char =:= 10) of true -> 
+        % item 385
+        true
+    ; false ->
+        % item 384
+        false
+    end
+.
+
+lex(Text) ->
+    % item 253
+    State = {[], []},
+    % item 398
+    Lexer = create(State),
+    % item 313
+    Operators = create_operator_list(),
+    % item 256
+    FinalLexer = scan(Operators, Lexer, Text),
+    % item 255
+    {_, TokensInv} = get_data(FinalLexer),
+    % item 393
+    lists:reverse(TokensInv)
+.
+
+scan(Operators, Lexer, Text) ->
+    % item 319
+    case Text =:= [] of true -> 
+        % item 387
+        % item 367
+        Message = {whitespace, 32},
+        % item 366
+        send_event(Lexer, Message)
+    ; false ->
+        % item 322
+        [Char | Rest] = Text,
+        % item 323
+        Type = classify(Operators, Char),
+        Message = {Type, Char},
+        % item 325
+        Lexer2 = send_event(Lexer, Message),
+        % item 324
+        scan(Operators, Lexer2, Rest)
+    end
+.
+
+try_make_long_operator(State, Char) ->
+    % item 332
+    {[Old], Tokens} = State,
+    Text = [Old, Char],
+    % item 297
+    case is_long_operator(Text) of true -> 
+        % item 300
+        Token = {operator, Text},
+        % item 397
+        NewState = {[], [Token | Tokens]},
+        % item 301
+        {true, NewState}
+    ; false ->
+        % item 302
+        {false, []}
+    end
+.
+identifier(Message_, State) ->
+    case Message_ of
+    {whitespace, _} ->
+        % item 65
+        {next_state, idle, create_identifier(State)}
+    ;
+    {letter, Char} ->
+        % item 242
+        {next_state, identifier, add_char(State, Char)}
+    ;
+    {digit, Char} ->
+        % item 243
+        {next_state, identifier, add_char(State, Char)}
+    ;
+    {operator, Char} ->
+        % item 219
+        StateWithId = 
+         create_identifier(State),
+        % item 61
+        {next_state, operator, add_char(StateWithId, Char)}
+    ;
+    _ ->
+        throw({invalid_state, "Message not supported by state 'identifier'."})
+    end
+.
+idle(Message_, State) ->
+    case Message_ of
+    {whitespace, _} ->
+        % item 211
+        {next_state, idle, State}
+    ;
+    {dummy, _} ->
+        % item 211
+        {next_state, idle, State}
+    ;
+    {letter, Char} ->
+        % item 44
+        {next_state, identifier, add_char(State, Char)}
+    ;
+    {digit, Char} ->
+        % item 240
+        {next_state, number, add_char(State, Char)}
+    ;
+    {operator, Char} ->
+        % item 241
+        {next_state, operator, add_char(State, Char)}
+    ;
+    _ ->
+        throw({invalid_state, "Message not supported by state 'idle'."})
+    end
+.
+number(Message_, State) ->
+    case Message_ of
+    {whitespace, _} ->
+        % item 82
+        {next_state, idle, create_number(State)}
+    ;
+    {letter, Char} ->
+        % item 244
+        {next_state, number, add_char(State, Char)}
+    ;
+    {digit, Char} ->
+        % item 245
+        {next_state, number, add_char(State, Char)}
+    ;
+    {operator, Char} ->
+        % item 226
+        StateWithNum =
+         create_number(State),
+        % item 227
+        {next_state, operator, add_char(StateWithNum, Char)}
+    ;
+    _ ->
+        throw({invalid_state, "Message not supported by state 'number'."})
+    end
+.
+operator(Message_, State) ->
+    case Message_ of
+    {whitespace, _} ->
+        % item 229
+        {next_state, idle, create_operator(State)}
+    ;
+    {letter, Char} ->
+        % item 230
+        StateWithOp =
+         create_operator(State),
+        % item 93
+        {next_state, identifier, add_char(StateWithOp, Char)}
+    ;
+    {digit, Char} ->
+        % item 231
+        StateWithOp =
+         create_operator(State),
+        % item 246
+        {next_state, number, add_char(StateWithOp, Char)}
+    ;
+    {operator, Char} ->
+        % item 233
+        {IsLong, StateWithLong} =
+         try_make_long_operator(State, Char),
+        % item 103
+        case IsLong of true -> 
+            % item 234
+            {next_state, idle, StateWithLong}
+        ; false ->
+            % item 235
+            StateWithOp =
+             create_operator(State),
+            % item 247
+            {next_state, operator, add_char(StateWithOp, Char)}
+        end
+    ;
+    _ ->
+        throw({invalid_state, "Message not supported by state 'operator'."})
+    end
+.
+
+create(State) ->
+    {state_machine, idle, State}.
+
+get_state(Machine) ->
+    {state_machine, StateName, _} = Machine,
+    StateName.
+
+get_data(Machine) ->
+    {state_machine, _, State } = Machine,
+    State.
+
+send_event(Machine, Event) ->
+    {state_machine, StateName, State} = Machine,
+    NewState = 
+    case StateName of
+    identifier ->
+        identifier(Event, State);
+    idle ->
+        idle(Event, State);
+    number ->
+        number(Event, State);
+    operator ->
+        operator(Event, State);
+    _ ->
+        throw({invalid_state, "Unsupported state"})
+    end,
+    {next_state, NextStateName, NextState} = NewState,
+    {state_machine, NextStateName, NextState}.
+
+

+ 38 - 0
examples/Erlang/fsm/readme.txt

@@ -0,0 +1,38 @@
+DRAKON-Erlang state machine demo
+================================
+
+DRAKON Editor can generate state machines for Erlang.
+
+There are 2 kinds of generated state machines:
+
+1. gen_fsm-based behaviour.
+The generated state machine will live in a separate process.
+Benefits:
+- The machine can be a full member of the supervision tree, enjoying all benefits of OTP.
+- Timeouts can be used.
+- Process dictionary can be used.
+
+2. Standalone state machine.
+The generated state machine will be just a tuple in the memory.
+Benefits:
+- Very lightweight.
+- No need to think about termination.
+
+code_door.drn contains an gen_fsm-based state machine.
+lexer.drn contains a standalone state machine.
+
+How to run
+----------
+1. Start Erlang from the current directory:
+	erl
+2. In the Erlang window, compile the gen_fsm state machine:
+	c(code_door).
+Don't worry about the warnings. They come from unimplemented behaviour methods.
+You can implement them, if you want.
+3. Compile the standalone state machine:
+	c(lexer).
+4. Compile the launcher:
+	c(fsm_demo).
+5. Run the demo:
+	fsm_demo:run().
+	

BIN
examples/Erlang/gen_server/musician.drn


+ 181 - 0
examples/Erlang/gen_server/musician.erl

@@ -0,0 +1,181 @@
+% Autogenerated with DRAKON Editor 1.26
+
+-module(musician).
+-export([code_change/3, handle_call/3, handle_cast/2, handle_info/2, init/1, run/0, start_link/2, stop/1, terminate/2]).
+-behaviour(gen_server).
+
+-record(state, {name="", role, skill=good}).
+-define(DELAY, 750).
+
+code_change(_OldVsn, State, _Extra) ->
+    % item 75
+    {ok, State}
+.
+
+first_names() ->
+    % item 11
+    ["Valerie", "Arnold", "Carlos", "Dorothy", "Keesha",
+        "Phoebe", "Ralphie", "Tim", "Wanda", "Janet"]
+.
+
+handle_call(Message, _From, State) ->
+    % item 38
+    case Message =:= stop of true -> 
+        % item 41
+        {stop, normal, ok, State}
+    ; false ->
+        % item 43
+        {noreply, State, ?DELAY}
+    end
+.
+
+handle_cast(_Message, State) ->
+    % item 49
+    {noreply, State, ?DELAY}
+.
+
+handle_info(timeout, State) ->
+    % item 55
+    #state {
+    	name = Name,
+    	skill = Skill
+    } = State,
+    case Skill of
+        good ->
+            % item 62
+            io:format("~s produced sound!~n",[Name]),
+            % item 68
+            {noreply, State, ?DELAY}
+        ;
+        bad ->
+            % item 63
+            case random:uniform(5) =:= 1 of true -> 
+                % item 66
+                io:format(
+                  "~s played a false note. Uh oh~n",
+                  [Name]
+                ),
+                % item 69
+                {stop, bad_note, State}
+            ; false ->
+                % item 62
+                io:format("~s produced sound!~n",[Name]),
+                % item 68
+                {noreply, State, ?DELAY}
+            end
+        ;
+        _ ->
+        throw("Unexpected switch value")
+    end
+.
+
+init([Role, Skill]) ->
+    % item 96
+    process_flag(trap_exit, true),
+    % item 6
+    random:seed(now()),
+    % item 29
+    TimeToPlay = random:uniform(3000),
+    Name = pick_name(),
+    % item 30
+    io:format(
+      "Musician ~s, playing the ~s entered the room~n",
+      [Name, Role]
+    ),
+    % item 31
+    State = #state {
+    	name = Name,
+    	role = Role,
+    	skill = Skill
+    },
+    % item 32
+    {ok, State, TimeToPlay}
+.
+
+last_names() ->
+    % item 16
+    ["Frizzle", "Perlstein", "Ramon", "Ann", "Franklin",
+        "Terese", "Tennelli", "Jamal", "Li", "Perlstein"]
+.
+
+pick_name() ->
+    % item 21
+    First = random_element(first_names()),
+    Last = random_element(last_names()),
+    % item 42
+    First ++ " " ++ Last
+.
+
+random_element(List) ->
+    % item 27
+    Length = length(List),
+    Index = random:uniform(Length),
+    % item 28
+    lists:nth(Index, List)
+.
+
+run() ->
+    % item 114
+    start_link(bass, bad),
+    % item 116
+    start_link(cello, good),
+    % item 115
+    timer:sleep(10000),
+    % item 117
+    stop(cello)
+.
+
+start_link(Role, Skill) ->
+    % item 102
+    gen_server:start_link(
+    	{local, Role},
+    	?MODULE,
+    	[Role, Skill], 
+    	[]
+    )
+.
+
+stop(Role) ->
+    % item 108
+    gen_server:call(Role, stop)
+.
+
+terminate(Reason, State) ->
+    % item 91
+    #state {
+    	name = Name,
+    	role = Role
+    } = State,
+    case Reason of
+        normal ->
+            % item 92
+            io:format(
+             "~s left the room (~s)~n",
+             [Name, Role]
+            )
+        ;
+        bad_note ->
+            % item 93
+            io:format(
+             "~s sucks! kicked that member out of the band! (~s)~n",
+             [Name, Role]
+            )
+        ;
+        shutdown ->
+            % item 94
+            io:format(
+             "The manager is mad and fired the whole band! "
+             ++ "~s just got back to playing in the subway~n",
+             [Name]
+            )
+        ;
+       _ ->
+            % item 95
+            io:format(
+             "~s has been kicked out (~s)",
+             [Name, Role]
+            )
+    end
+.
+
+

+ 9 - 0
examples/Erlang/gen_server/readme.txt

@@ -0,0 +1,9 @@
+A gen_server demo for DRAKON-Erlang.
+
+How to run:
+1. Start Erlang shell.
+	erl
+2. Compile
+	c(musician).
+3. Run
+	musician:run().

+ 0 - 9
examples/Erlang/readme.txt

@@ -1,9 +0,0 @@
-DRAKON-Erlang demo.
-To run the demo:
-1. cd to this directory.
-2. Start Erlang interpreter:
-	> erl
-3. Compile erldemo.erl:
-	1> c(erldemo).
-4. Run the demo:
-	2> erldemo:main().

+ 0 - 130
examples/Erlang/sel2.erl

@@ -1,130 +0,0 @@
-% Autogenerated with DRAKON Editor 1.26
-
--module(sel2).
--export([case1/1, case2/1, case3/0, case4/0, case5/0, short/1]).
-
-case1(Arg1) ->
-    % item 52
-    case Arg1 =:= 0 of true -> 
-        % item 55
-        io:format("0~n", [])
-    ; false ->
-        case Arg1 of
-            ok ->
-                % item 16
-                io:format("ok~n", [])
-            ;
-            error ->
-                % item 16
-                io:format("ok~n", [])
-            ;
-            {foo, Message} ->
-                % item 14
-                io:format("ok ~p~n", [Message])
-            ;
-            {bar, Message} ->
-                % item 51
-                io:format("bar ~p~n", [Message])
-            ;
-            _ ->
-            throw("Unexpected switch value")
-        end
-    end
-.
-
-case2(Arg1) ->
-    case Arg1 of
-        ok ->
-            % item 44
-            io:format("ok~n", []),
-            % item 56
-            io:format("ok2~n", []),
-            % item 57
-            io:format("ok3~n", [])
-        ;
-        {foo, Message} ->
-            % item 42
-            io:format("~p~n", [Message]),
-            % item 57
-            io:format("ok3~n", [])
-        ;
-       _ ->
-            % item 47
-            io:format("else~n", []),
-            % item 57
-            io:format("ok3~n", [])
-    end
-.
-
-case3() ->
-    receive
-        ok ->
-            % item 70
-            io:format("ok~n", []),
-            % item 74
-            io:format("ok2~n", []),
-            % item 75
-            io:format("ok3~n", [])
-        ;
-        {foo, Message} ->
-            % item 68
-            io:format("~p~n", [Message]),
-            % item 75
-            io:format("ok3~n", [])
-        ;
-       _ ->
-            % item 73
-            io:format("else~n", []),
-            % item 75
-            io:format("ok3~n", [])
-    end
-.
-
-case4() ->
-    receive
-        ok ->
-            % item 90
-            ok
-        ;
-        {error, _Message} ->
-            % item 91
-            error
-        ;
-        _ ->
-            % item 92
-            other
-        
-        after 6000 ->
-            % item 93
-            timeout
-    end
-.
-
-case5() ->
-    receive
-        ok ->
-            % item 109
-            ok
-        ;
-        {error, _Message} ->
-            % item 110
-            error
-        
-        after 6000 ->
-            % item 112
-            timeout
-    end
-.
-
-short(Arg) ->
-    % item 22
-    case ((Arg =:= 0) orelse (Arg =:= 1)) orelse (Arg =:= 2) of true -> 
-        % item 27
-        true
-    ; false ->
-        % item 28
-        false
-    end
-.
-
-

+ 18 - 0
examples/Erlang/supervision/de_sup.erl

@@ -0,0 +1,18 @@
+-module(de_sup).
+-behaviour(supervisor).
+
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init(_) ->
+    RestartStrategy = {one_for_one, 10, 3600},
+    Children = [
+       {events, {events, start_link, []}, permanent, 2000, worker, [events]},
+       {session_root_sup, {session_root_sup, start_link, []}, permanent, 5000, supervisor, [session_root_sup]},
+       {ybed_sup, {ybed_sup, start_link, []}, permanent, 5000, supervisor, [ybed_sup]},
+       {de_server, {de_server, start_link, []}, permanent, 2000, worker, [de_server]}
+    ],
+    {ok, {RestartStrategy, Children}}.
+

+ 65 - 0
examples/Erlang/supervision/readme.txt

@@ -0,0 +1,65 @@
+# How to generate a supervision tree in DRAKON Editor.
+
+1. In DRAKON Editor, change the language to "Erlang". File / File properties... / Language: Erlang
+2. Create one or more structure diagrams. Insert / New diagram... / Structure diagram
+3. Icons of type "Entity" will be workers. Icons of type "Entity with fields" (with a horizontal line) will be supervisors.
+
+Workers must be leaves (they should not have any children).
+DRAKON Editor will generate .erl files for each supervisor except "empty" supervisors.
+An "empty" supervisor has an empty bottom part.
+"Empty" supervisors should not have children.
+
+It is possible to have many supervision trees.
+
+## Fields
+
+### Supervisor
+
+<name>
+restart = temporary | transient | permanent
+shutdown = infinity | brutal_kill | <milliseconds>
+-------
+strategy = one_for_one | one_for_all | rest_for_one | simple_one_for_one
+max_restart = <0 or max number of restarts before giving up>
+max_time = <1 or time to try in milliseconds before giving up>
+
+Information above the horizontal line describes the supervisor itself.
+Information below the line is related to the children.
+
+Example
+
+session_root_sup
+restart  = permanent
+shutdown = 5000
+-----------------
+strategy    = simple_one_for_one
+max_restart = 0
+max_time    = 1
+
+The supervisor which is the root of a tree should have only its name in the upper part of the icon.
+
+Example
+
+mega_root_sup
+-----------------
+strategy    = simple_one_for_one
+max_restart = 0
+max_time    = 1
+
+
+### Worker
+
+<name>
+restart = temporary | transient | permanent
+shutdown = infinity | brutal_kill | <milliseconds>
+
+Example
+
+session_element
+restart = temporary
+shutdown = brutal_kill
+
+
+DRAKON Editor will not generate source files for workers.
+It is up to the developer to create worker modules.
+A worker is expected to have a start_link/0 function.

+ 17 - 0
examples/Erlang/supervision/session_root_sup.erl

@@ -0,0 +1,17 @@
+-module(session_root_sup).
+-behaviour(supervisor).
+
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init(_) ->
+    RestartStrategy = {one_for_all, 5, 3600},
+    Children = [
+       {session_sup, {session_sup, start_link, []}, permanent, 5000, supervisor, [session_sup]},
+       {session_store, {session_store, start_link, []}, permanent, 2000, worker, [session_store]},
+       {foobar_sup, {foobar_sup, start_link, []}, permanent, 5555, supervisor, [foobar_sup]}
+    ],
+    {ok, {RestartStrategy, Children}}.
+

+ 15 - 0
examples/Erlang/supervision/session_sup.erl

@@ -0,0 +1,15 @@
+-module(session_sup).
+-behaviour(supervisor).
+
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init(_) ->
+    RestartStrategy = {simple_one_for_one, 0, 1},
+    Children = [
+       {session_element, {session_element, start_link, []}, temporary, brutal_kill, worker, [session_element]}
+    ],
+    {ok, {RestartStrategy, Children}}.
+

BIN
examples/Erlang/sel2.drn


+ 5 - 0
examples/Erlang/supervision/super.erl

@@ -0,0 +1,5 @@
+% Autogenerated with DRAKON Editor 1.26
+
+-module(super).
+
+

+ 15 - 0
examples/Erlang/supervision/ybed_sup.erl

@@ -0,0 +1,15 @@
+-module(ybed_sup).
+-behaviour(supervisor).
+
+-export([start_link/0]).
+-export([init/1]).
+
+start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+init(_) ->
+    RestartStrategy = {one_for_all, 0, 1},
+    Children = [
+       {ybed, {ybed, start_link, []}, permanent, 5000, worker, [ybed]}
+    ],
+    {ok, {RestartStrategy, Children}}.
+