gisele 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/CHANGELOG.md +33 -13
  2. data/Gemfile +3 -2
  3. data/Gemfile.lock +6 -3
  4. data/LICENCE.md +1 -1
  5. data/README.md +5 -2
  6. data/Rakefile +0 -8
  7. data/examples/rectal-cancer-pathway/RectalCancerPathway.gis +1 -1
  8. data/gisele.gemspec +3 -2
  9. data/gisele.noespec +4 -3
  10. data/lib/gisele.rb +11 -7
  11. data/lib/gisele/command.rb +28 -19
  12. data/lib/gisele/compiling.rb +2 -0
  13. data/lib/gisele/compiling/to_glts.rb +125 -0
  14. data/lib/gisele/compiling/to_graph.rb +160 -0
  15. data/lib/gisele/compiling/to_graph.yml +20 -0
  16. data/lib/gisele/language.rb +22 -36
  17. data/lib/gisele/language/ast/bool_and.rb +1 -1
  18. data/lib/gisele/language/ast/bool_expr.rb +9 -1
  19. data/lib/gisele/language/ast/bool_not.rb +1 -1
  20. data/lib/gisele/language/ast/bool_or.rb +1 -1
  21. data/lib/gisele/language/ast/case_st.rb +1 -1
  22. data/lib/gisele/language/ast/else_clause.rb +1 -1
  23. data/lib/gisele/language/ast/node.rb +4 -66
  24. data/lib/gisele/language/grammar.citrus +2 -2
  25. data/lib/gisele/language/grammar.sexp.yml +83 -80
  26. data/lib/gisele/language/processors.rb +2 -2
  27. data/lib/gisele/language/processors/elsif_flattener.rb +14 -13
  28. data/lib/gisele/language/processors/if_to_case.rb +20 -18
  29. data/lib/gisele/language/processors/scoping_helper.rb +32 -0
  30. data/lib/gisele/language/processors/sugar_removal.rb +10 -5
  31. data/lib/gisele/language/syntax/case_st.rb +1 -1
  32. data/lib/gisele/language/syntax/node.rb +6 -2
  33. data/lib/gisele/language/syntax/when_clause.rb +1 -1
  34. data/lib/gisele/loader.rb +2 -1
  35. data/lib/gisele/version.rb +1 -1
  36. data/spec/command/main/gisele_glts.cmd +1 -0
  37. data/spec/command/main/gisele_glts.stdout +85 -0
  38. data/spec/command/main/gisele_help.stdout +3 -2
  39. data/spec/spec_helper.rb +2 -3
  40. data/spec/test_examples.rb +2 -2
  41. data/spec/unit/compiling/test_to_glts.rb +20 -0
  42. data/spec/unit/compiling/test_to_graph.rb +19 -0
  43. data/spec/unit/language/ast/test_bool_expr.rb +50 -0
  44. data/spec/unit/language/grammar_sexp/test_fluent_def.rb +1 -1
  45. data/spec/unit/language/processors/test_elsif_flattener.rb +3 -3
  46. data/spec/unit/language/processors/test_if_to_case.rb +7 -7
  47. data/spec/unit/language/processors/test_scoping_helper.rb +45 -0
  48. data/spec/unit/language/syntax/grammar/test_bool_expr.rb +2 -2
  49. data/spec/unit/language/syntax/grammar/test_boolean_literal.rb +2 -2
  50. data/spec/unit/language/syntax/grammar/test_case_st.rb +2 -2
  51. data/spec/unit/language/syntax/grammar/test_event.rb +2 -2
  52. data/spec/unit/language/syntax/grammar/test_event_name.rb +2 -2
  53. data/spec/unit/language/syntax/grammar/test_event_set.rb +2 -3
  54. data/spec/unit/language/syntax/grammar/test_fluent_def.rb +2 -2
  55. data/spec/unit/language/syntax/grammar/test_if_st.rb +2 -2
  56. data/spec/unit/language/syntax/grammar/test_par_st.rb +2 -2
  57. data/spec/unit/language/syntax/grammar/test_process_statement.rb +2 -2
  58. data/spec/unit/language/syntax/grammar/test_seq_st.rb +2 -2
  59. data/spec/unit/language/syntax/grammar/test_spaces.rb +2 -2
  60. data/spec/unit/language/syntax/grammar/test_spacing.rb +2 -3
  61. data/spec/unit/language/syntax/grammar/test_task_def.rb +2 -2
  62. data/spec/unit/language/syntax/grammar/test_task_name.rb +2 -2
  63. data/spec/unit/language/syntax/grammar/test_task_start_or_end.rb +2 -2
  64. data/spec/unit/language/syntax/grammar/test_trackvar_def.rb +2 -2
  65. data/spec/unit/language/syntax/grammar/test_unit_def.rb +2 -2
  66. data/spec/unit/language/syntax/grammar/test_variable_name.rb +24 -3
  67. data/spec/unit/language/syntax/grammar/test_when_clause.rb +2 -2
  68. data/spec/unit/language/syntax/grammar/test_while_st.rb +2 -2
  69. data/spec/unit/language/syntax/to_ast/test_bool_expr.rb +5 -1
  70. data/spec/unit/language/syntax/to_ast/test_case_st.rb +1 -1
  71. data/spec/unit/language/syntax/to_ast/test_else_clause.rb +1 -1
  72. data/spec/unit/language/syntax/to_ast/test_elsif_clause.rb +1 -1
  73. data/spec/unit/language/syntax/to_ast/test_event_set.rb +1 -1
  74. data/spec/unit/language/syntax/to_ast/test_fluent_def.rb +1 -1
  75. data/spec/unit/language/syntax/to_ast/test_if_st.rb +1 -1
  76. data/spec/unit/language/syntax/to_ast/test_par_st.rb +1 -1
  77. data/spec/unit/language/syntax/to_ast/test_seq_st.rb +1 -1
  78. data/spec/unit/language/syntax/to_ast/test_task_call_st.rb +1 -1
  79. data/spec/unit/language/syntax/to_ast/test_task_def.rb +1 -1
  80. data/spec/unit/language/syntax/to_ast/test_trackvar_def.rb +1 -1
  81. data/spec/unit/language/syntax/to_ast/test_unit_def.rb +1 -1
  82. data/spec/unit/language/syntax/to_ast/test_var_ref.rb +1 -1
  83. data/spec/unit/language/syntax/to_ast/test_when_clause.rb +1 -1
  84. data/spec/unit/language/syntax/to_ast/test_while_st.rb +1 -1
  85. data/spec/unit/language/test_syntax.rb +36 -38
  86. data/spec/unit/test_gisele.rb +1 -1
  87. metadata +189 -190
  88. data/lib/gisele/language/ast.rb +0 -14
  89. data/lib/gisele/language/ast/helpers.rb +0 -43
  90. data/lib/gisele/language/ast/unit_def.rb +0 -10
  91. data/lib/gisele/language/grammar.dot.yml +0 -19
  92. data/lib/gisele/language/processors/to_graph.rb +0 -146
  93. data/lib/gisele/language/rewriter.rb +0 -60
  94. data/lib/gisele/language/rewriter/helper.rb +0 -41
  95. data/lib/gisele/language/rewriter/scoping.rb +0 -34
  96. data/lib/gisele/language/rewriter/work_on_nodes.rb +0 -30
  97. data/lib/gisele/language/syntax.rb +0 -29
  98. data/spec/unit/language/ast/test_node.rb +0 -82
  99. data/spec/unit/language/processors/test_to_graph.rb +0 -17
  100. data/spec/unit/language/rewriter/test_helper.rb +0 -87
  101. data/spec/unit/language/rewriter/test_scoping.rb +0 -46
  102. data/spec/unit/language/rewriter/test_work_on_nodes.rb +0 -45
  103. data/spec/unit/language/test_ast.rb +0 -38
  104. data/spec/unit/language/test_rewriter.rb +0 -81
  105. data/spec/unit/test_language.rb +0 -35
@@ -1,6 +1,26 @@
1
+ # 0.5.0 / 2012-02-26
2
+
3
+ * Major enhancements
4
+
5
+ * All s-expression tools have been moved to a separated project called `Sexpr` (see
6
+ https://github.com/blambeau/sexpr). This implies a lot of changes here, but mostly
7
+ to private APIs. In particular, the commandline tool and the language grammar have not
8
+ changed.
9
+ * A --glts option has been added to the gisele commandline tool, that outputs a guarded
10
+ labeled transition system. The option follows the g-hMSC -> g-LTS semantics defined
11
+ in [Dam09, Lam11].
12
+
13
+ * Breaking changes
14
+
15
+ * `ToGraph` has been moved under `Gisele::Compiling` instead of `Gisele::Language`.
16
+ * `Language::AST::Node#dot_attributes` has been removed as it is very specific to the
17
+ ToGraph compiler and not a language construction.
18
+ * In the same vein, language/grammar.dot.yml -> compiling/to_graph.yml
19
+ * Also, `Language::DOT_ATTRIBUTES` -> `Compiling::ToGraph::DOT_ATTRIBUTES`
20
+
1
21
  # 0.4.0 / 2012-02-20
2
22
 
3
- * Major enhancement
23
+ * Major enhancements
4
24
 
5
25
  * The grammar is going to be stable very soon now (expect backward compatible additions,
6
26
  maybe). As an helper to work with the grammar, a YAML file describing the structure of
@@ -9,9 +29,9 @@
9
29
  * Breaking changes
10
30
 
11
31
  * The :nop statement has been renamed :nop_st.
12
- * The kind of the AST nodes for fluent and tracking variable definitions have been renamed
13
- :fluent_def and :trackvar_def. This is actually a bugfix but that might break other code
14
- relying on 0.3.0.
32
+ * The kind of the AST nodes for fluent and tracking variable definitions have been
33
+ renamed :fluent_def and :trackvar_def. This is actually a bugfix but that might break
34
+ other code relying on 0.3.0.
15
35
 
16
36
  # 0.3.0 / 2012-02-20
17
37
 
@@ -24,8 +44,8 @@
24
44
 
25
45
  * Minor enhancements
26
46
 
27
- * The --graph option now outputs one graph for each task_def in the unit. Previously only
28
- the graph of the last task definition was printed.
47
+ * The --graph option now outputs one graph for each task_def in the unit. Previously
48
+ only the graph of the last task definition was printed.
29
49
 
30
50
  * Bugfixes
31
51
 
@@ -34,10 +54,10 @@
34
54
 
35
55
  * Breaking changes
36
56
 
37
- * The syntax and AST of a task definition has changed. The "refinement ... end" construct
38
- has been removed and replaced by an explicit process statement. Accordingly, the nodes
39
- task_refinement and task_signature have been removed as well. The AST signature of a task
40
- definition is now as follows:
57
+ * The syntax and AST of a task definition has changed. The "refinement ... end"
58
+ construct has been removed and replaced by an explicit process statement. Accordingly,
59
+ the nodes task_refinement and task_signature have been removed as well. The AST
60
+ signature of a task definition is now as follows:
41
61
 
42
62
  [:task_def, "TaskName", (fluent_def, trackvar_def, task_def)*, explicit_statement]
43
63
 
@@ -52,9 +72,9 @@
52
72
 
53
73
  * Boolean literals (true, false) are now explicitly represented in boolean expressions,
54
74
  under a :bool_lit AST node.
55
- * All statements and clauses relying on boolean conditions (if_st, while_st, elsif_clause,
56
- when_clause) have now an explicit :bool_expr node as first child. Previously, a subnode
57
- of the boolean grammar was used.
75
+ * All statements and clauses relying on boolean conditions (if_st, while_st,
76
+ elsif_clause, when_clause) have now an explicit :bool_expr node as first child.
77
+ Previously, a subnode of the boolean grammar was used.
58
78
 
59
79
  # 0.1.0 / 2012-02-17
60
80
 
data/Gemfile CHANGED
@@ -6,12 +6,13 @@ group :runtime do
6
6
  gem "quickl", "~> 0.4.3"
7
7
  gem "awesome_print", "~> 1.0"
8
8
  gem "yargi", "~> 0.2.0"
9
- gem "sexp_grammar", "~> 0.1.0"
9
+ gem "sexpr", "~> 0.5.0"
10
+ gem "stamina-core", "~> 0.5.3"
10
11
  end
11
12
 
12
13
  group :development do
13
14
  gem "rake", "~> 0.9.2"
14
15
  gem "bundler", "~> 1.0"
15
- gem "rspec", "~> 2.8.0"
16
+ gem "rspec", "~> 2.8"
16
17
  gem "wlang", "~> 0.10.2"
17
18
  end
@@ -15,7 +15,9 @@ GEM
15
15
  rspec-expectations (2.8.0)
16
16
  diff-lcs (~> 1.1.2)
17
17
  rspec-mocks (2.8.0)
18
- sexp_grammar (0.1.0)
18
+ sexpr (0.5.0)
19
+ stamina-core (0.5.3)
20
+ quickl (~> 0.4.3)
19
21
  wlang (0.10.2)
20
22
  yargi (0.2.0)
21
23
 
@@ -30,7 +32,8 @@ DEPENDENCIES
30
32
  epath (~> 0.0.1)
31
33
  quickl (~> 0.4.3)
32
34
  rake (~> 0.9.2)
33
- rspec (~> 2.8.0)
34
- sexp_grammar (~> 0.1.0)
35
+ rspec (~> 2.8)
36
+ sexpr (~> 0.5.0)
37
+ stamina-core (~> 0.5.3)
35
38
  wlang (~> 0.10.2)
36
39
  yargi (~> 0.2.0)
data/LICENCE.md CHANGED
@@ -19,4 +19,4 @@
19
19
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
20
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
21
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Gisele
2
2
 
3
+ [![Build Status](https://secure.travis-ci.org/blambeau/gisele.png)](http://travis-ci.org/blambeau/gisele)
4
+ [![Dependency Status](https://gemnasium.com/blambeau/gisele.png)](https://gemnasium.com/blambeau/gisele)
5
+
3
6
  Gisele is a Process Analyzer Toolset
4
7
 
5
8
  ## Description
@@ -14,7 +17,7 @@ This project requires an installation of ruby >= 1.9.2. Then,
14
17
  gem install gisele
15
18
  gisele --help
16
19
 
17
- For contributors (UCLouvain students, in particular), please consider the following
20
+ For contributors (UCLouvain students, in particular), please consider the following
18
21
  scenario:
19
22
 
20
23
  gem install bundler --pre
@@ -26,5 +29,5 @@ scenario:
26
29
 
27
30
  ## Contributing
28
31
 
29
- Gisele is distributed under a MIT license. The common github workflow (fork/pull request)
32
+ Gisele is distributed under a MIT license. The common github workflow (fork/pull request)
30
33
  applies. Please take contact with Bernard Lambeau with any question.
data/Rakefile CHANGED
@@ -1,11 +1,3 @@
1
- begin
2
- gem "bundler", "~> 1.0"
3
- require "bundler/setup"
4
- rescue LoadError => ex
5
- puts ex.message
6
- abort "Bundler failed to load, (did you run 'gem install bundler' ?)"
7
- end
8
-
9
1
  # Dynamically load the gem spec
10
2
  $gemspec_file = File.expand_path('../gisele.gemspec', __FILE__)
11
3
  $gemspec = Kernel.eval(File.read($gemspec_file))
@@ -61,4 +61,4 @@ task RectalCancerPathway
61
61
  end
62
62
  end
63
63
 
64
- end
64
+ end
@@ -125,14 +125,15 @@ Gem::Specification.new do |s|
125
125
  #
126
126
  s.add_development_dependency("rake", "~> 0.9.2")
127
127
  s.add_development_dependency("bundler", "~> 1.0")
128
- s.add_development_dependency("rspec", "~> 2.8.0")
128
+ s.add_development_dependency("rspec", "~> 2.8")
129
129
  s.add_development_dependency("wlang", "~> 0.10.2")
130
130
  s.add_dependency("citrus", "~> 2.4")
131
131
  s.add_dependency("epath", "~> 0.0.1")
132
132
  s.add_dependency("quickl", "~> 0.4.3")
133
133
  s.add_dependency("awesome_print", "~> 1.0")
134
134
  s.add_dependency("yargi", "~> 0.2.0")
135
- s.add_dependency("sexp_grammar", "~> 0.1.0")
135
+ s.add_dependency("sexpr", "~> 0.5.0")
136
+ s.add_dependency("stamina-core", "~> 0.5.3")
136
137
 
137
138
  # The version of ruby required by this gem
138
139
  #
@@ -12,7 +12,7 @@ variables:
12
12
  upper:
13
13
  Gisele
14
14
  version:
15
- 0.4.0
15
+ 0.5.0
16
16
  summary: |-
17
17
  Gisele is a Process Analyzer Toolset
18
18
  description: |-
@@ -30,9 +30,10 @@ variables:
30
30
  - {name: quickl, version: "~> 0.4.3", groups: [runtime]}
31
31
  - {name: awesome_print, version: "~> 1.0", groups: [runtime]}
32
32
  - {name: yargi, version: "~> 0.2.0", groups: [runtime]}
33
- - {name: sexp_grammar, version: "~> 0.1.0", groups: [runtime]}
33
+ - {name: sexpr, version: "~> 0.5.0", groups: [runtime]}
34
+ - {name: stamina-core, version: "~> 0.5.3", groups: [runtime]}
34
35
  #
35
36
  - {name: rake, version: "~> 0.9.2", groups: [development]}
36
37
  - {name: bundler, version: "~> 1.0", groups: [development]}
37
- - {name: rspec, version: "~> 2.8.0", groups: [development]}
38
+ - {name: rspec, version: "~> 2.8", groups: [development]}
38
39
  - {name: wlang, version: "~> 0.10.2", groups: [development]}
@@ -6,15 +6,19 @@ require_relative 'gisele/errors'
6
6
  #
7
7
  module Gisele
8
8
 
9
- def parse(input)
10
- Language::Syntax::parse(input)
9
+ def parse(*args)
10
+ Language::parse(*args)
11
11
  end
12
- module_function :parse
13
12
 
14
- def ast(input)
15
- Language::Syntax::ast(input)
13
+ def ast(*args)
14
+ Language::sexpr(*args)
16
15
  end
17
- module_function :ast
18
16
 
17
+ def sexpr(*args)
18
+ Language::sexpr(*args)
19
+ end
20
+
21
+ extend(self)
19
22
  end # module Gisele
20
- require_relative 'gisele/language'
23
+ require_relative 'gisele/language'
24
+ require_relative 'gisele/compiling'
@@ -31,18 +31,25 @@ module Gisele
31
31
 
32
32
  # Install options
33
33
  options do |opt|
34
- @print_ast = nil
35
- opt.on('--ast=[MODE]', 'Prints the process abstract syntax tree (debug,ruby)') do |value|
36
- @print_ast = (value || "debug").to_sym
37
- end
38
34
  @sugar = true
39
35
  opt.on('--no-sugar', 'Apply syntactic sugar removal') do
40
36
  @sugar = false
41
37
  end
42
- @print_graph = nil
43
- opt.on('--graph=[MODE]', 'Converts and print a graph (dot)') do |value|
44
- @print_graph = (value || "dot").to_sym
38
+
39
+ @compile_mode = [:ast, "debug"]
40
+ opt.on('--ast=[MODE]',
41
+ 'Compile as an abstract syntax tree (debug,ruby)') do |value|
42
+ @compile_mode = [:ast, (value || "debug").to_sym]
43
+ end
44
+ opt.on('--graph=[MODE]',
45
+ 'Compile as a workflow graph (dot)') do |value|
46
+ @compile_mode = [:graph, (value || "dot").to_sym]
47
+ end
48
+ opt.on('--glts=[MODE]',
49
+ 'Compile as guarded labeled transition system (dot)') do |value|
50
+ @compile_mode = [:glts, (value || "dot").to_sym]
45
51
  end
52
+
46
53
  opt.on_tail('--help', "Show this help message") do
47
54
  raise Quickl::Help
48
55
  end
@@ -59,31 +66,33 @@ module Gisele
59
66
  end
60
67
 
61
68
  ast = Gisele.ast(file)
62
- ast = Language::SugarRemoval.new.call(ast) unless @sugar
69
+ ast = Language::SugarRemoval.call(ast) unless @sugar
63
70
 
64
- print_ast(ast, @print_ast) if @print_ast
65
- print_graph(ast, @print_graph) if @print_graph
71
+ send :"compile_#{@compile_mode.first}", ast, *@compile_mode[1..-1]
66
72
  end
67
73
 
68
74
  private
69
75
 
70
- def print_ast(ast, option)
76
+ def compile_ast(ast, option)
71
77
  require 'awesome_print'
72
- options = case option
73
- when :ruby
74
- {index: false, plain: true}
75
- else
76
- {}
77
- end
78
+ options = {}
79
+ options = {index: false, plain: true} if option == :ruby
78
80
  ap ast, options
79
81
  end
80
82
 
81
- def print_graph(ast, option)
82
- graphs = Gisele::Language::ToGraph.new.call(ast)
83
+ def compile_graph(ast, option)
84
+ graphs = Gisele::Compiling::ToGraph.call(ast)
83
85
  graphs.each do |graph|
84
86
  puts graph.to_dot
85
87
  end
86
88
  end
87
89
 
90
+ def compile_glts(ast, option)
91
+ glts = Gisele::Compiling::ToGlts.call(ast)
92
+ glts.each do |g|
93
+ puts g.to_dot(&Gisele::Compiling::ToGlts::DOT_REWRITER)
94
+ end
95
+ end
96
+
88
97
  end # class Command
89
98
  end # module Gisele
@@ -0,0 +1,2 @@
1
+ require_relative 'compiling/to_graph'
2
+ require_relative 'compiling/to_glts'
@@ -0,0 +1,125 @@
1
+ module Gisele
2
+ module Compiling
3
+ class ToGlts < Sexpr::Rewriter
4
+ grammar Language
5
+
6
+ DOT_REWRITER = lambda{|elm,kind|
7
+ case kind
8
+ when :automaton
9
+ {:rankdir => "LR"}
10
+ when :state
11
+ {:shape => "circle",
12
+ :style => "filled",
13
+ :color => "black",
14
+ :fillcolor => (elm.initial? ? "green" : "white")}
15
+ when :edge
16
+ label = elm[:guard] ? "[#{elm[:guard].label}]" : elm[:symbol]
17
+ {:label => label || ''}
18
+ end
19
+ }
20
+
21
+ # if/elsif/else -> guarded commands
22
+ use Language::IfToCase
23
+
24
+ def on_unit_def(sexpr)
25
+ sexpr.
26
+ sexpr_body.
27
+ select{|n| n.first == :task_def}.
28
+ map{|taskdef| apply(taskdef) }
29
+ end
30
+
31
+ def on_task_def(sexpr)
32
+ @glts = Stamina::Automaton.new
33
+
34
+ entry = add_state(sexpr, :initial => true)
35
+ exit = add_state(sexpr)
36
+ c_entry, c_exit = apply(sexpr.last)
37
+ connect(entry, c_entry)
38
+ connect(c_exit, exit)
39
+
40
+ @glts
41
+ end
42
+
43
+ def on_seq_st(sexpr)
44
+ mine = entry_and_exit(sexpr)
45
+ current = mine.first
46
+ sexpr.sexpr_body.each do |child|
47
+ c_entry, c_exit = apply(child)
48
+ connect(current, c_entry)
49
+ current = c_exit
50
+ end
51
+ connect(current, mine.last)
52
+ mine
53
+ end
54
+ alias :on_par_st :on_seq_st
55
+
56
+ def on_case_st(sexpr)
57
+ cond, *clauses = sexpr.sexpr_body
58
+
59
+ entry, exit = entry_and_exit(sexpr)
60
+
61
+ diamond = add_state(sexpr)
62
+ connect(entry, diamond)
63
+
64
+ clauses.each do |clause|
65
+ c_entry, c_exit = apply(clause.last)
66
+ connect(diamond, c_entry, clause[1])
67
+ connect(c_exit, exit)
68
+ end
69
+
70
+ [entry, exit]
71
+ end
72
+
73
+ def on_while_st(sexpr)
74
+ cond, dost, = sexpr.sexpr_body
75
+
76
+ entry, exit = entry_and_exit(sexpr)
77
+
78
+ diamond = add_state(sexpr)
79
+ connect(entry, diamond)
80
+
81
+ c_entry, c_exit = apply(sexpr.last)
82
+
83
+ connect(diamond, exit, cond.negate)
84
+ connect(diamond, c_entry, cond)
85
+ connect(c_exit, diamond)
86
+
87
+ [entry, exit]
88
+ end
89
+
90
+ def on_task_call_st(sexpr)
91
+ entry, exit = entry_and_exit(sexpr)
92
+ middle = add_state(sexpr)
93
+ connect(entry, middle, transition(sexpr, "start"))
94
+ connect(middle, exit, transition(sexpr, "end"))
95
+ [entry, exit]
96
+ end
97
+
98
+ private
99
+
100
+ def entry_and_exit(sexpr)
101
+ @glts.add_n_states(2)
102
+ end
103
+
104
+ def add_state(sexpr, attrs = nil)
105
+ @glts.add_state(attrs || {})
106
+ end
107
+
108
+ def connect(source, target, attrs = {:symbol => nil})
109
+ attrs = transition(attrs) unless Hash===attrs
110
+ @glts.connect(source, target, attrs)
111
+ end
112
+
113
+ def transition(sexpr, kind = nil)
114
+ raise UnexpectedNodeError, "Node expected, got #{sexpr}" unless Sexpr===sexpr
115
+ case sexpr.first
116
+ when :task_call_st then {:symbol => "#{sexpr.label}:#{kind}"}
117
+ when :bool_expr then {:symbol => "[guard]", :guard => sexpr}
118
+ else
119
+ raise UnexpectedNodeError, "Unexpected event kind #{sexpr.inspect}"
120
+ end
121
+ end
122
+
123
+ end # class ToGlts
124
+ end # module Compiling
125
+ end # module Gisele
@@ -0,0 +1,160 @@
1
+ module Gisele
2
+ module Compiling
3
+ class ToGraph < Sexpr::Rewriter
4
+ grammar Language
5
+
6
+ # We do not support the elsif syntactic sugar here; rewrite it as 'else if'.
7
+ use Language::ElsifFlattener
8
+
9
+ # This is a marker for the graph nodes we can remove later.
10
+ module Connector; end
11
+
12
+ def on_unit_def(sexpr)
13
+ sexpr.
14
+ sexpr_body.
15
+ select{|n| n.first == :task_def}.
16
+ map{|taskdef| apply(taskdef) }
17
+ end
18
+
19
+ def on_task_def(sexpr)
20
+ @graph = Yargi::Digraph.new
21
+
22
+ entry, exit = add_vertex(sexpr), add_vertex(sexpr)
23
+ c_entry, c_exit = apply(sexpr.last)
24
+ connect(entry, c_entry)
25
+ connect(c_exit, exit)
26
+
27
+ @graph.vertices(Connector).each do |vertex|
28
+ next unless vertex.out_edges.size == 1
29
+ target = vertex.out_edges.first.target
30
+ @graph.reconnect(vertex.in_edges, nil, target)
31
+ @graph.remove_vertex(vertex)
32
+ end
33
+
34
+ @graph
35
+ end
36
+
37
+ def on_seq_st(sexpr)
38
+ mine = entry_and_exit(sexpr)
39
+ current = mine.first
40
+ sexpr.sexpr_body.each do |child|
41
+ c_entry, c_exit = apply(child)
42
+ connect(current, c_entry)
43
+ current = c_exit
44
+ end
45
+ connect(current, mine.last)
46
+ mine
47
+ end
48
+
49
+ def on_par_st(sexpr)
50
+ entry, exit = add_vertex(sexpr), add_vertex(sexpr)
51
+ sexpr.sexpr_body.each do |child|
52
+ c_entry, c_exit = apply(child)
53
+ connect(entry, c_entry)
54
+ connect(c_exit, exit)
55
+ end
56
+ [entry, exit]
57
+ end
58
+
59
+ def on_if_st(sexpr)
60
+ cond, then_clause, else_clause, = sexpr.sexpr_body
61
+
62
+ entry, exit = entry_and_exit(sexpr)
63
+
64
+ diamond = add_vertex(sexpr)
65
+ connect(entry, diamond)
66
+
67
+ c_entry, c_exit = apply(then_clause)
68
+ connect(diamond, c_entry, true_ast_sexpr)
69
+ connect(c_exit, exit)
70
+
71
+ if else_clause
72
+ c_entry, c_exit = apply(else_clause.last)
73
+ connect(diamond, c_entry, false_ast_sexpr)
74
+ connect(c_exit, exit)
75
+ else
76
+ connect(diamond, exit, false_ast_sexpr)
77
+ end
78
+
79
+ [entry, exit]
80
+ end
81
+
82
+ def on_case_st(sexpr)
83
+ cond, *clauses = sexpr.sexpr_body
84
+
85
+ entry, exit = entry_and_exit(sexpr)
86
+
87
+ diamond = add_vertex(sexpr)
88
+ connect(entry, diamond)
89
+
90
+ clauses.each do |clause|
91
+ c_entry, c_exit = apply(clause.last)
92
+ connect(diamond, c_entry, clause)
93
+ connect(c_exit, exit)
94
+ end
95
+
96
+ [entry, exit]
97
+ end
98
+
99
+
100
+ def on_while_st(sexpr)
101
+ cond, dost, = sexpr.sexpr_body
102
+
103
+ entry, exit = entry_and_exit(sexpr)
104
+
105
+ diamond = add_vertex(sexpr)
106
+ connect(entry, diamond)
107
+
108
+ c_entry, c_exit = apply(sexpr.last)
109
+
110
+ connect(diamond, exit, false_ast_sexpr)
111
+ connect(diamond, c_entry, true_ast_sexpr)
112
+ connect(c_exit, diamond)
113
+
114
+ [entry, exit]
115
+ end
116
+
117
+ def on_task_call_st(sexpr)
118
+ entry, exit = entry_and_exit(sexpr)
119
+ task = add_vertex(sexpr)
120
+ connect(entry, task)
121
+ connect(task, exit)
122
+ [entry, exit]
123
+ end
124
+
125
+ private
126
+
127
+ def add_vertex(sexpr)
128
+ @graph.add_vertex(dot_attributes(sexpr))
129
+ end
130
+
131
+ def entry_and_exit(sexpr, tag = Connector)
132
+ @graph.add_n_vertices(2, tag)
133
+ end
134
+
135
+ def connect(source, target, sexpr = nil)
136
+ @graph.connect(source, target, dot_attributes(sexpr))
137
+ end
138
+
139
+ def false_ast_sexpr
140
+ sexpr(parse("false", :root => :bool_expr))
141
+ end
142
+
143
+ def true_ast_sexpr
144
+ sexpr(parse("true", :root => :bool_expr))
145
+ end
146
+
147
+ DOT_ATTRIBUTES = YAML.load_file(Path.dir/"to_graph.yml")
148
+ def dot_attributes(sexpr)
149
+ if Sexpr===sexpr
150
+ attrs = DOT_ATTRIBUTES["graphviz"][sexpr.first.to_s] || {}
151
+ attrs = attrs.merge(:label => sexpr.label) if sexpr.respond_to?(:label)
152
+ attrs
153
+ else
154
+ {} # sometimes, sexpr is simply nil
155
+ end
156
+ end
157
+
158
+ end # class ToGraph
159
+ end # module Compiling
160
+ end # module Gisele