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,14 +0,0 @@
1
- module Gisele
2
- module Language
3
- module AST
4
-
5
- def node(arg, markers = {})
6
- AST::Helpers.node(arg, markers)
7
- end
8
- module_function :node
9
-
10
- end # module AST
11
- end # module Language
12
- end # module Gisele
13
- require_relative 'ast/helpers'
14
- require_relative 'ast/node'
@@ -1,43 +0,0 @@
1
- module Gisele
2
- module Language
3
- module AST
4
- module Helpers
5
-
6
- def ast(arg, markers = {})
7
- return node(arg, markers) if looks_a_node?(arg)
8
- ast(Syntax.ast(arg), markers)
9
- end
10
-
11
- def node(arg, markers = {})
12
- return arg if arg.is_a?(Node)
13
- unless looks_a_node?(arg)
14
- raise ArgumentError, "Array expected, #{arg.inspect} found."
15
- end
16
- extend_node(arg, markers).tap do |node|
17
- node.children.each{|c| node(c) if looks_a_node?(c)}
18
- end
19
- end
20
-
21
- private
22
-
23
- def looks_a_node?(arg)
24
- arg.is_a?(Node) or (arg.is_a?(Array) and arg.first.is_a?(Symbol))
25
- end
26
-
27
- def extend_node(arg, markers)
28
- mod = ast_module(arg)
29
- arg.extend(mod).tap do |node|
30
- node.markers = markers
31
- end
32
- end
33
-
34
- def ast_module(node)
35
- modname = Language.rule2mod(node.first)
36
- AST.const_get(modname) rescue Node
37
- end
38
-
39
- extend(self)
40
- end # module Helpers
41
- end # module AST
42
- end # module Language
43
- end # module Gisele
@@ -1,10 +0,0 @@
1
- module Gisele
2
- module Language
3
- module AST
4
- module UnitDef
5
- include Node
6
-
7
- end # module UnitDef
8
- end # module AST
9
- end # module Language
10
- end # module Gisele
@@ -1,19 +0,0 @@
1
- task_def:
2
- shape: circle
3
- style: filled
4
- fillcolor: black
5
- fixed: true
6
- width: 0.1
7
- task_call_st:
8
- shape: box
9
- while_st:
10
- shape: diamond
11
- if_st:
12
- shape: diamond
13
- case_st:
14
- shape: diamond
15
- par_st:
16
- shape: box
17
- height: 0.1
18
- style: filled
19
- fillcolor: black
@@ -1,146 +0,0 @@
1
- module Gisele
2
- module Language
3
- class ToGraph < Rewriter
4
- module Connector; end
5
-
6
- def on_unit_def(node)
7
- node.
8
- children.
9
- select{|n| n.first == :task_def}.
10
- map{|taskdef| call(taskdef) }
11
- end
12
-
13
- def on_task_def(node)
14
- @graph = Yargi::Digraph.new
15
-
16
- entry, exit = add_vertex(node), add_vertex(node)
17
-
18
- # flatten all elsif
19
- c_entry, c_exit = call(ElsifFlattener.new.call(node.last))
20
- connect(entry, c_entry)
21
- connect(c_exit, exit)
22
-
23
- @graph.vertices(Connector).each do |vertex|
24
- next unless vertex.out_edges.size == 1
25
- target = vertex.out_edges.first.target
26
- @graph.reconnect(vertex.in_edges, nil, target)
27
- @graph.remove_vertex(vertex)
28
- end
29
-
30
- @graph
31
- end
32
-
33
- def on_seq_st(node)
34
- mine = entry_and_exit(node)
35
- current = mine.first
36
- node.children.each do |child|
37
- c_entry, c_exit = call(child)
38
- connect(current, c_entry)
39
- current = c_exit
40
- end
41
- connect(current, mine.last)
42
- mine
43
- end
44
-
45
- def on_par_st(node)
46
- entry, exit = add_vertex(node), add_vertex(node)
47
- node.children.each do |child|
48
- c_entry, c_exit = call(child)
49
- connect(entry, c_entry)
50
- connect(c_exit, exit)
51
- end
52
- [entry, exit]
53
- end
54
-
55
- def on_if_st(node)
56
- cond, then_clause, else_clause, = node.children
57
-
58
- entry, exit = entry_and_exit(node)
59
-
60
- diamond = add_vertex(node)
61
- connect(entry, diamond)
62
-
63
- c_entry, c_exit = call(then_clause)
64
- connect(diamond, c_entry, true_ast_node)
65
- connect(c_exit, exit)
66
-
67
- if else_clause
68
- c_entry, c_exit = call(else_clause.last)
69
- connect(diamond, c_entry, false_ast_node)
70
- connect(c_exit, exit)
71
- else
72
- connect(diamond, exit, false_ast_node)
73
- end
74
-
75
- [entry, exit]
76
- end
77
-
78
- def on_case_st(node)
79
- cond, *clauses = node.children
80
-
81
- entry, exit = entry_and_exit(node)
82
-
83
- diamond = add_vertex(node)
84
- connect(entry, diamond)
85
-
86
- clauses.each do |clause|
87
- c_entry, c_exit = call(clause.last)
88
- connect(diamond, c_entry, clause)
89
- connect(c_exit, exit)
90
- end
91
-
92
- [entry, exit]
93
- end
94
-
95
-
96
- def on_while_st(node)
97
- cond, dost, = node.children
98
-
99
- entry, exit = entry_and_exit(node)
100
-
101
- diamond = add_vertex(node)
102
- connect(entry, diamond)
103
-
104
- c_entry, c_exit = call(node.last)
105
-
106
- connect(diamond, exit, false_ast_node)
107
- connect(diamond, c_entry, true_ast_node)
108
- connect(c_exit, diamond)
109
-
110
- [entry, exit]
111
- end
112
-
113
- def on_task_call_st(node)
114
- entry, exit = entry_and_exit(node)
115
- task = add_vertex(node)
116
- connect(entry, task)
117
- connect(task, exit)
118
- [entry, exit]
119
- end
120
-
121
- private
122
-
123
- def add_vertex(node)
124
- @graph.add_vertex(node.dot_attributes)
125
- end
126
-
127
- def entry_and_exit(node, tag = Connector)
128
- @graph.add_n_vertices(2, tag)
129
- end
130
-
131
- def connect(source, target, node = nil)
132
- marks = node.nil? ? {} : node.dot_attributes
133
- @graph.connect(source, target, marks)
134
- end
135
-
136
- def false_ast_node
137
- Syntax.ast("false", :root => :bool_expr)
138
- end
139
-
140
- def true_ast_node
141
- Syntax.ast("true", :root => :bool_expr)
142
- end
143
-
144
- end # class SugarRemoval
145
- end # module Language
146
- end # module Gisele
@@ -1,60 +0,0 @@
1
- module Gisele
2
- module Language
3
- class Rewriter
4
- include AST::Helpers
5
-
6
- ### class methods
7
-
8
- def self.helpers
9
- @helpers ||= [ WorkOnNodes.new ]
10
- end
11
-
12
- def self.add_helper(helper)
13
- unless helpers.empty?
14
- helpers.last.next_in_chain = helper
15
- end
16
- helpers << helper
17
- end
18
-
19
- ### instance methods
20
-
21
- attr_reader :mainflow
22
-
23
- def initialize(options = {})
24
- @options = options
25
- @mainflow = options[:mainflow] || self
26
- end
27
-
28
- def call(node)
29
- help(node) do |n|
30
- meth = :"on_#{node.first}"
31
- meth = :"on_missing" unless respond_to?(meth)
32
- send(meth, node)
33
- end
34
- end
35
-
36
- def on_missing(node)
37
- raise UnexpectedNodeError, "Unexpected node: #{node.inspect}"
38
- end
39
-
40
- def copy_and_applyall(node)
41
- node.copy do |memo,child|
42
- memo << (child.is_a?(AST::Node) ? call(child) : child)
43
- end
44
- end
45
-
46
- private
47
-
48
- def help(node)
49
- @first_helper ||= self.class.helpers.first
50
- @first_helper.call(self, node) do |_,n|
51
- yield(n)
52
- end
53
- end
54
-
55
- end # class Rewriter
56
- end # module Language
57
- end # module Gisele
58
- require_relative 'rewriter/helper'
59
- require_relative 'rewriter/work_on_nodes'
60
- require_relative 'rewriter/scoping'
@@ -1,41 +0,0 @@
1
- module Gisele
2
- module Language
3
- class Rewriter
4
- class Helper
5
-
6
- attr_accessor :next_in_chain
7
-
8
- def self.install_on(rewriter)
9
- methods = const_get(:Methods)
10
- rewriter.module_eval do
11
- include methods
12
- end
13
- rewriter.add_helper(new)
14
- end
15
-
16
- def call(rw, node, &bl)
17
- meth = :"on_#{node.first}"
18
- meth = :"on_missing" unless respond_to?(meth)
19
- send(meth, rw, node) do |r,n|
20
- next_call(r, n, bl)
21
- end
22
- end
23
-
24
- def on_missing(rw, node)
25
- yield(rw, node)
26
- end
27
-
28
- private
29
-
30
- def next_call(rw, node, toplevel)
31
- if nic = next_in_chain
32
- nic.call(rw, node, &toplevel)
33
- else
34
- toplevel.call(rw, node)
35
- end
36
- end
37
-
38
- end # class Helper
39
- end # class Rewriter
40
- end # module Language
41
- end # module Gisele
@@ -1,34 +0,0 @@
1
- module Gisele
2
- module Language
3
- class Rewriter
4
- class Scoping < Helper
5
-
6
- module Methods
7
-
8
- def scope_stack
9
- @scope_stack ||= []
10
- end
11
-
12
- def with_scope(scope)
13
- scope_stack.push(scope)
14
- result = yield
15
- scope_stack.pop
16
- result
17
- end
18
-
19
- end # module Methods
20
-
21
- def on_missing(rw, node)
22
- if node.rule_name.to_s =~ /_def/
23
- rw.with_scope(node) do
24
- yield(rw, node)
25
- end
26
- else
27
- yield(rw, node)
28
- end
29
- end
30
-
31
- end # module Scoping
32
- end # class Rewriter
33
- end # module Language
34
- end # module Gisele
@@ -1,30 +0,0 @@
1
- module Gisele
2
- module Language
3
- class Rewriter
4
- class WorkOnNodes < Helper
5
- include AST::Helpers
6
-
7
- def call(rw, node, &bl)
8
- node = pre_call(node)
9
- tran = next_call(rw, node, bl)
10
- post_call(tran)
11
- end
12
-
13
- protected
14
-
15
- def pre_call(node)
16
- unless looks_a_node?(node)
17
- msg = "AST node expected, got #{node.inspect}"
18
- raise ArgumentError, msg, caller
19
- end
20
- node(node)
21
- end
22
-
23
- def post_call(t)
24
- looks_a_node?(t) ? node(t) : t
25
- end
26
-
27
- end # module WorkOnNodes
28
- end # class Rewriter
29
- end # module Language
30
- end # module Gisele
@@ -1,29 +0,0 @@
1
- require_relative 'syntax/node'
2
- module Gisele
3
- module Language
4
- module Syntax
5
- Citrus.load(File.expand_path('../grammar', __FILE__))
6
-
7
- def parse(input, options = {})
8
- source = parsing_source(input)
9
- Grammar.parse(source, options)
10
- end
11
- module_function :parse
12
-
13
- def ast(input, parse_options = {})
14
- parse(input, parse_options).to_ast
15
- end
16
- module_function :ast
17
-
18
- private
19
-
20
- def parsing_source(input)
21
- input = File.read(input.to_path) if input.respond_to?(:to_path)
22
- input = input.to_str if input.respond_to?(:to_str)
23
- input
24
- end
25
- module_function :parsing_source
26
-
27
- end # module Syntax
28
- end # module Language
29
- end # module Gisele
@@ -1,82 +0,0 @@
1
- require 'spec_helper'
2
- module Gisele::Language::AST
3
- describe Node do
4
-
5
- describe 'rule_name' do
6
- it 'returns the first array element' do
7
- node([:hello]).rule_name.should eq(:hello)
8
- end
9
- end
10
-
11
- describe 'children' do
12
-
13
- it 'returns all but the rule name' do
14
- node([:hello, "world", "!"]).children.should eq(["world", "!"])
15
- end
16
-
17
- it 'returns an empty array when no children' do
18
- node([:hello]).children.should eq([])
19
- end
20
-
21
- end # children
22
-
23
- describe 'markers' do
24
-
25
- it 'defaults to an empty hash' do
26
- node([:hello]).markers.should eq({})
27
- end
28
-
29
- end # markers
30
-
31
- describe 'copy' do
32
-
33
- it 'collects block results ala `inject`' do
34
- source = node([:unit_def, "world", "gisele"])
35
- target = source.copy do |memo,child|
36
- memo << child.upcase
37
- end
38
- target.should be_a(UnitDef)
39
- target.should eq([:unit_def, "WORLD", "GISELE"])
40
- end
41
-
42
- it 'returns a real equal copy when no children' do
43
- source = node([:unit_def])
44
- target = source.copy do |memo,child| end
45
- target.should eq(source)
46
- target.object_id.should_not eq(source.object_id)
47
- target.should be_a(UnitDef)
48
- end
49
-
50
- it 'keeps the markers unchanged' do
51
- node = node([:unit_def], {:hello => "World"})
52
- copy = node.copy do |memo,child| end
53
- copy.markers.should eq({:hello => "World"})
54
- copy.markers.object_id.should_not eq(node.markers.object_id)
55
- end
56
-
57
- end
58
-
59
- describe 'dup' do
60
-
61
- it 'duplicates the underlying array' do
62
- arr = [:unit_def, "etc."]
63
- node(arr).dup.should eq(arr)
64
- end
65
-
66
- it 'ensures duplicated array is still a node' do
67
- arr = [:unit_def, "etc."]
68
- node(arr).dup.should be_a(UnitDef)
69
- node(arr).dup.should be_a(Node)
70
- end
71
-
72
- it 'keeps the markers unchanged' do
73
- node = node([:unit_def, "etc."], {:hello => "World"})
74
- copy = node.dup
75
- copy.markers.should eq({:hello => "World"})
76
- copy.markers.object_id.should_not eq(node.markers.object_id)
77
- end
78
-
79
- end # dup
80
-
81
- end
82
- end