gisele-language 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/Gemfile +12 -0
  3. data/Gemfile.lock +26 -0
  4. data/LICENCE.md +22 -0
  5. data/Manifest.txt +13 -0
  6. data/README.md +7 -0
  7. data/Rakefile +11 -0
  8. data/gisele-language.gemspec +188 -0
  9. data/gisele-language.noespec +24 -0
  10. data/lib/gisele/language/ast/bool_and.rb +14 -0
  11. data/lib/gisele/language/ast/bool_expr.rb +22 -0
  12. data/lib/gisele/language/ast/bool_not.rb +14 -0
  13. data/lib/gisele/language/ast/bool_or.rb +14 -0
  14. data/lib/gisele/language/ast/case_st.rb +14 -0
  15. data/lib/gisele/language/ast/else_clause.rb +14 -0
  16. data/lib/gisele/language/ast/elsif_clause.rb +14 -0
  17. data/lib/gisele/language/ast/if_st.rb +14 -0
  18. data/lib/gisele/language/ast/node.rb +35 -0
  19. data/lib/gisele/language/ast/task_call_st.rb +14 -0
  20. data/lib/gisele/language/ast/var_ref.rb +14 -0
  21. data/lib/gisele/language/ast/when_clause.rb +14 -0
  22. data/lib/gisele/language/ast/while_st.rb +14 -0
  23. data/lib/gisele/language/grammar.citrus +236 -0
  24. data/lib/gisele/language/grammar.sexp.yml +83 -0
  25. data/lib/gisele/language/processors/elsif_flattener.rb +36 -0
  26. data/lib/gisele/language/processors/if_to_case.rb +65 -0
  27. data/lib/gisele/language/processors/scoping_helper.rb +32 -0
  28. data/lib/gisele/language/processors/sugar_removal.rb +17 -0
  29. data/lib/gisele/language/processors.rb +4 -0
  30. data/lib/gisele/language/syntax/bool_and.rb +14 -0
  31. data/lib/gisele/language/syntax/bool_expr.rb +14 -0
  32. data/lib/gisele/language/syntax/bool_lit.rb +14 -0
  33. data/lib/gisele/language/syntax/bool_not.rb +14 -0
  34. data/lib/gisele/language/syntax/bool_or.rb +14 -0
  35. data/lib/gisele/language/syntax/bool_paren.rb +14 -0
  36. data/lib/gisele/language/syntax/case_st.rb +19 -0
  37. data/lib/gisele/language/syntax/else_clause.rb +14 -0
  38. data/lib/gisele/language/syntax/elsif_clause.rb +16 -0
  39. data/lib/gisele/language/syntax/event_set.rb +15 -0
  40. data/lib/gisele/language/syntax/fluent_def.rb +18 -0
  41. data/lib/gisele/language/syntax/if_st.rb +18 -0
  42. data/lib/gisele/language/syntax/implicit_seq_st.rb +16 -0
  43. data/lib/gisele/language/syntax/node.rb +40 -0
  44. data/lib/gisele/language/syntax/par_st.rb +14 -0
  45. data/lib/gisele/language/syntax/seq_st.rb +14 -0
  46. data/lib/gisele/language/syntax/st_list.rb +14 -0
  47. data/lib/gisele/language/syntax/task_call_st.rb +14 -0
  48. data/lib/gisele/language/syntax/task_def.rb +18 -0
  49. data/lib/gisele/language/syntax/trackvar_def.rb +19 -0
  50. data/lib/gisele/language/syntax/unit_def.rb +14 -0
  51. data/lib/gisele/language/syntax/var_ref.rb +14 -0
  52. data/lib/gisele/language/syntax/when_clause.rb +16 -0
  53. data/lib/gisele/language/syntax/while_st.rb +16 -0
  54. data/lib/gisele/language.rb +31 -0
  55. data/lib/gisele-language/loader.rb +3 -0
  56. data/lib/gisele-language/version.rb +16 -0
  57. data/lib/gisele-language.rb +19 -0
  58. data/spec/fixtures/tasks/complete.gis +40 -0
  59. data/spec/fixtures/tasks/simple.ast +51 -0
  60. data/spec/fixtures/tasks/simple.gis +16 -0
  61. data/spec/language/ast/test_bool_expr.rb +50 -0
  62. data/spec/language/grammar_sexp/test_case_st.rb +20 -0
  63. data/spec/language/grammar_sexp/test_event_set.rb +14 -0
  64. data/spec/language/grammar_sexp/test_fluent_def.rb +18 -0
  65. data/spec/language/grammar_sexp/test_initially.rb +18 -0
  66. data/spec/language/grammar_sexp/test_nop_st.rb +10 -0
  67. data/spec/language/grammar_sexp/test_when_clause.rb +12 -0
  68. data/spec/language/processors/test_elsif_flattener.rb +94 -0
  69. data/spec/language/processors/test_if_to_case.rb +105 -0
  70. data/spec/language/processors/test_scoping_helper.rb +45 -0
  71. data/spec/language/syntax/grammar/test_bool_expr.rb +34 -0
  72. data/spec/language/syntax/grammar/test_boolean_literal.rb +17 -0
  73. data/spec/language/syntax/grammar/test_case_st.rb +60 -0
  74. data/spec/language/syntax/grammar/test_event.rb +18 -0
  75. data/spec/language/syntax/grammar/test_event_name.rb +21 -0
  76. data/spec/language/syntax/grammar/test_event_set.rb +26 -0
  77. data/spec/language/syntax/grammar/test_fluent_def.rb +21 -0
  78. data/spec/language/syntax/grammar/test_if_st.rb +21 -0
  79. data/spec/language/syntax/grammar/test_par_st.rb +11 -0
  80. data/spec/language/syntax/grammar/test_process_statement.rb +19 -0
  81. data/spec/language/syntax/grammar/test_seq_st.rb +11 -0
  82. data/spec/language/syntax/grammar/test_spaces.rb +19 -0
  83. data/spec/language/syntax/grammar/test_spacing.rb +17 -0
  84. data/spec/language/syntax/grammar/test_task_def.rb +35 -0
  85. data/spec/language/syntax/grammar/test_task_name.rb +19 -0
  86. data/spec/language/syntax/grammar/test_task_start_or_end.rb +17 -0
  87. data/spec/language/syntax/grammar/test_trackvar_def.rb +21 -0
  88. data/spec/language/syntax/grammar/test_unit_def.rb +29 -0
  89. data/spec/language/syntax/grammar/test_variable_name.rb +51 -0
  90. data/spec/language/syntax/grammar/test_when_clause.rb +21 -0
  91. data/spec/language/syntax/grammar/test_while_st.rb +11 -0
  92. data/spec/language/syntax/to_ast/test_bool_expr.rb +32 -0
  93. data/spec/language/syntax/to_ast/test_case_st.rb +47 -0
  94. data/spec/language/syntax/to_ast/test_else_clause.rb +13 -0
  95. data/spec/language/syntax/to_ast/test_elsif_clause.rb +15 -0
  96. data/spec/language/syntax/to_ast/test_event_set.rb +24 -0
  97. data/spec/language/syntax/to_ast/test_fluent_def.rb +26 -0
  98. data/spec/language/syntax/to_ast/test_if_st.rb +39 -0
  99. data/spec/language/syntax/to_ast/test_par_st.rb +12 -0
  100. data/spec/language/syntax/to_ast/test_seq_st.rb +12 -0
  101. data/spec/language/syntax/to_ast/test_task_call_st.rb +10 -0
  102. data/spec/language/syntax/to_ast/test_task_def.rb +44 -0
  103. data/spec/language/syntax/to_ast/test_trackvar_def.rb +26 -0
  104. data/spec/language/syntax/to_ast/test_unit_def.rb +28 -0
  105. data/spec/language/syntax/to_ast/test_var_ref.rb +12 -0
  106. data/spec/language/syntax/to_ast/test_when_clause.rb +15 -0
  107. data/spec/language/syntax/to_ast/test_while_st.rb +24 -0
  108. data/spec/language/test_syntax.rb +51 -0
  109. data/spec/spec_helper.rb +44 -0
  110. data/spec/test_gisele-language.rb +8 -0
  111. data/tasks/gem.rake +73 -0
  112. data/tasks/spec_test.rake +71 -0
  113. metadata +269 -0
@@ -0,0 +1,40 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module Node
5
+
6
+ def to_ast
7
+ Language::sexpr(value, {:citrus_match => self})
8
+ end
9
+
10
+ def value
11
+ _to_ast
12
+ end
13
+
14
+ end # module Node
15
+ end # module Syntax
16
+ end # module Language
17
+ end # module Gisele
18
+ require_relative 'event_set'
19
+ require_relative 'fluent_def'
20
+ require_relative 'trackvar_def'
21
+ require_relative 'var_ref'
22
+ require_relative 'bool_lit'
23
+ require_relative 'bool_paren'
24
+ require_relative 'bool_not'
25
+ require_relative 'bool_and'
26
+ require_relative 'bool_or'
27
+ require_relative 'bool_expr'
28
+ require_relative 'st_list'
29
+ require_relative 'implicit_seq_st'
30
+ require_relative 'task_call_st'
31
+ require_relative 'seq_st'
32
+ require_relative 'par_st'
33
+ require_relative 'while_st'
34
+ require_relative 'if_st'
35
+ require_relative 'else_clause'
36
+ require_relative 'elsif_clause'
37
+ require_relative 'case_st'
38
+ require_relative 'when_clause'
39
+ require_relative 'task_def'
40
+ require_relative 'unit_def'
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module ParSt
5
+ include Node
6
+
7
+ def _to_ast
8
+ [:par_st] + captures[:st_list].first.value
9
+ end
10
+
11
+ end # module ParSt
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module SeqSt
5
+ include Node
6
+
7
+ def _to_ast
8
+ [:seq_st] + captures[:st_list].first.value
9
+ end
10
+
11
+ end # module SeqSt
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module StList
5
+ include Node
6
+
7
+ def value
8
+ captures[:explicit_statement].map{|x| x.to_ast}
9
+ end
10
+
11
+ end # module StList
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module TaskCallSt
5
+ include Node
6
+
7
+ def _to_ast
8
+ [:task_call_st, strip]
9
+ end
10
+
11
+ end # module TaskCallSt
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,18 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module TaskDef
5
+ include Node
6
+
7
+ def _to_ast
8
+ name = captures[:task_name].first.strip
9
+ defs = captures[:some_def].map{|x| x.to_ast}
10
+ ref = captures[:explicit_statement].map{|x| x.to_ast}.first
11
+ ref = [:nop_st] unless ref
12
+ [:task_def, name] + defs + [ref]
13
+ end
14
+
15
+ end # module TaskDef
16
+ end # module Syntax
17
+ end # module Language
18
+ end # module Gisele
@@ -0,0 +1,19 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module TrackvarDef
5
+ include Node
6
+
7
+ def _to_ast
8
+ name = captures[:variable_name].first.strip
9
+ init, term = captures[:event_set].map{|x| x.to_ast}
10
+ term = [:event_set] unless term
11
+ initval = captures[:initially_def].first
12
+ initval = (initval && !initval.empty?) ? initval.value : nil
13
+ [:trackvar_def, name, init, term, initval]
14
+ end
15
+
16
+ end # module TrackvarDef
17
+ end # module Syntax
18
+ end # module Language
19
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module UnitDef
5
+ include Node
6
+
7
+ def _to_ast
8
+ [:unit_def] + captures[:task_def].map{|x| x.to_ast}
9
+ end
10
+
11
+ end # module UnitDef
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,14 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module VarRef
5
+ include Node
6
+
7
+ def _to_ast
8
+ [:var_ref, strip]
9
+ end
10
+
11
+ end # module VarRef
12
+ end # module Syntax
13
+ end # module Language
14
+ end # module Gisele
@@ -0,0 +1,16 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module WhenClause
5
+ include Node
6
+
7
+ def _to_ast
8
+ cond = captures[:bool_expr].first.to_ast
9
+ dost = captures[:process_statement].first.to_ast
10
+ [:when_clause, cond, dost]
11
+ end
12
+
13
+ end # module WhenClause
14
+ end # module Syntax
15
+ end # module Language
16
+ end # module Gisele
@@ -0,0 +1,16 @@
1
+ module Gisele
2
+ module Language
3
+ module Syntax
4
+ module WhileSt
5
+ include Node
6
+
7
+ def _to_ast
8
+ cond = captures[:bool_expr].first.to_ast
9
+ dost = captures[:process_statement].first.to_ast
10
+ [:while_st, cond, dost]
11
+ end
12
+
13
+ end # module WhileSt
14
+ end # module Syntax
15
+ end # module Language
16
+ end # module Gisele
@@ -0,0 +1,31 @@
1
+ require 'yaml'
2
+ module Gisele
3
+
4
+ # Load the Language through Sexpr
5
+ Language = Sexpr.load Path.dir/"language/grammar.sexp.yml"
6
+
7
+ # Load syntax nodes, abstract syntax nodes, and processors
8
+ require_relative 'language/syntax/node'
9
+ require_relative 'language/ast/node'
10
+ require_relative 'language/processors'
11
+
12
+ # Force loading the Citrus parser now
13
+ Language.parser.parser
14
+
15
+ module Language
16
+
17
+ # By default, Sexpr will find for abstract nodes under Language itself. We
18
+ # override that behavior here and let it know that the AST module is the
19
+ # parent of all ast nodes.
20
+ def tagging_reference
21
+ AST
22
+ end
23
+
24
+ # The tagging function (from s-expr kind to AST module) is not complete so far.
25
+ # This allows us to at least include the AST:Node module in all s-expressions.
26
+ def default_tagging_module
27
+ AST::Node
28
+ end
29
+
30
+ end # module Language
31
+ end # module Gisele
@@ -0,0 +1,3 @@
1
+ require "citrus"
2
+ require "path"
3
+ require "sexpr"
@@ -0,0 +1,16 @@
1
+ module Gisele
2
+ module Language
3
+ module Version
4
+
5
+ MAJOR = 0
6
+ MINOR = 5
7
+ TINY = 0
8
+
9
+ def self.to_s
10
+ [ MAJOR, MINOR, TINY ].join('.')
11
+ end
12
+
13
+ end
14
+ VERSION = Version.to_s
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ require "gisele-language/loader"
2
+ require_relative "gisele/language"
3
+ require "gisele-language/version"
4
+ module Gisele
5
+
6
+ def parse(*args)
7
+ Language::parse(*args)
8
+ end
9
+
10
+ def ast(*args)
11
+ Language::sexpr(*args)
12
+ end
13
+
14
+ def sexpr(*args)
15
+ Language::sexpr(*args)
16
+ end
17
+
18
+ extend(self)
19
+ end
@@ -0,0 +1,40 @@
1
+ task Complete
2
+
3
+ trackvar everyOneHappy
4
+ {FirstTask:start}
5
+
6
+ fluent someoneHappy
7
+ {DrinkBeer:start, DrinkBeers:start},
8
+ {DoNothingSpecial:end}
9
+ initially false
10
+
11
+ task DrinkBeers
12
+ while not(drunk)
13
+ DrinkBeer
14
+ end
15
+ end
16
+
17
+ seq
18
+ FirstTask
19
+ if everyoneHappy
20
+ par
21
+ MakeJoy
22
+ DrinkBeers
23
+ end
24
+ elsif someoneHappy
25
+ DrinkBeer
26
+ else
27
+ DoNothingSpecial
28
+ end
29
+ while not(endOfTheDay)
30
+ case curState
31
+ when somethingToDo
32
+ DoSomething
33
+ when nothingToDo
34
+ DoNothing
35
+ else
36
+ WaitAndSee
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,51 @@
1
+ [
2
+ :unit_def,
3
+ [
4
+ :task_def,
5
+ "Simple",
6
+ [
7
+ :fluent_def,
8
+ "diagKnown",
9
+ [
10
+ :event_set,
11
+ "Diagnosis:start"
12
+ ],
13
+ [
14
+ :event_set,
15
+ "Treatment:end"
16
+ ],
17
+ nil
18
+ ],
19
+ [
20
+ :seq_st,
21
+ [
22
+ :if_st,
23
+ [
24
+ :bool_expr,
25
+ [
26
+ :bool_not,
27
+ [
28
+ :var_ref,
29
+ "diagKnown"
30
+ ]
31
+ ]
32
+ ],
33
+ [
34
+ :task_call_st,
35
+ "Diagnosis"
36
+ ],
37
+ [
38
+ :else_clause,
39
+ [
40
+ :task_call_st,
41
+ "NoDiag"
42
+ ]
43
+ ]
44
+ ],
45
+ [
46
+ :task_call_st,
47
+ "Treatment"
48
+ ]
49
+ ]
50
+ ]
51
+ ]
@@ -0,0 +1,16 @@
1
+ task Simple
2
+
3
+ fluent diagKnown
4
+ {Diagnosis:start},
5
+ {Treatment:end}
6
+
7
+ seq
8
+ if not(diagKnown)
9
+ Diagnosis
10
+ else
11
+ NoDiag
12
+ end
13
+ Treatment
14
+ end
15
+
16
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+ module Gisele::Language::AST
3
+ describe BoolExpr, "negate" do
4
+
5
+ def sexpr(expr, options = {})
6
+ Gisele.sexpr(Gisele.parse(expr, options))
7
+ end
8
+
9
+ subject{ sexpr(expr, :root => :bool_expr).negate }
10
+
11
+ shared_examples_for 'A negated bool_expr' do
12
+
13
+ it 'is consistently rewrited' do
14
+ (Gisele::Language[:bool_expr] === subject).should be_true
15
+ end
16
+
17
+ it 'is correctly tagged' do
18
+ subject.should be_a(Sexpr)
19
+ subject.should be_a(BoolExpr)
20
+ end
21
+
22
+ it 'has no immediate traceability marker' do
23
+ subject.citrus_match.should be_nil
24
+ end
25
+ end
26
+
27
+ describe "on a normal expression" do
28
+ let(:expr){ "x and y" }
29
+
30
+ it_behaves_like 'A negated bool_expr'
31
+
32
+ it "negates as expected" do
33
+ expected = sexpr("not(x and y)", :root => :bool_expr)
34
+ subject.should eq(expected)
35
+ end
36
+ end
37
+
38
+ describe "on a negated expression" do
39
+ let(:expr){ "not(x and y)" }
40
+
41
+ it_behaves_like 'A negated bool_expr'
42
+
43
+ it "removes the negation" do
44
+ expected = sexpr("x and y", :root => :bool_expr)
45
+ subject.should eq(expected)
46
+ end
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ module Gisele::Language
3
+ describe "the Sexp grammar", "case_st" do
4
+
5
+ it 'matches when no variable is specified' do
6
+ case_st = \
7
+ [:case_st, nil,
8
+ [:when_clause, [:bool_expr, [:bool_lit, true]], [:nop_st]] ]
9
+ (sexp_grammar[:case_st] === case_st).should be_true
10
+ end
11
+
12
+ it 'matches when a variable is specified' do
13
+ case_st = \
14
+ [:case_st, [:var_ref, "varName"],
15
+ [:when_clause, [:bool_expr, [:bool_lit, true]], [:nop_st]] ]
16
+ (sexp_grammar[:case_st] === case_st).should be_true
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ module Gisele::Language
3
+ describe "the Sexp grammar", "event_set" do
4
+
5
+ it 'matches an empty set' do
6
+ (sexp_grammar[:event_set] === [:event_set]).should be_true
7
+ end
8
+
9
+ it 'matches a non empty set' do
10
+ (sexp_grammar[:event_set] === [:event_set, "event", "Task:start"]).should be_true
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ module Gisele::Language
3
+ describe "the Sexp grammar", "fluent_def" do
4
+
5
+ let(:g){ Gisele::Language }
6
+
7
+ it 'matches an fluent with initial value' do
8
+ fluent = [:fluent_def, "name", [:event_set, "start"], [:event_set, "stop"], true]
9
+ (sexp_grammar[:fluent_def] === fluent).should be_true
10
+ end
11
+
12
+ it 'matches an fluent without initial value' do
13
+ fluent = [:fluent_def, "name", [:event_set, "start"], [:event_set, "stop"], nil]
14
+ (sexp_grammar[:fluent_def] === fluent).should be_true
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ module Gisele::Language
3
+ describe "the Sexp grammar", "initially" do
4
+
5
+ it 'matches true' do
6
+ (sexp_grammar[:initially] === true).should be_true
7
+ end
8
+
9
+ it 'matches false' do
10
+ (sexp_grammar[:initially] === false).should be_true
11
+ end
12
+
13
+ it 'matches nil' do
14
+ (sexp_grammar[:initially] === nil).should be_true
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ module Gisele::Language
3
+ describe "the Sexp grammar", "nop_st" do
4
+
5
+ it 'matches [:nop_st]' do
6
+ (sexp_grammar[:nop_st] === [:nop_st]).should be_true
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+ module Gisele::Language
3
+ describe "the Sexp grammar", "when_clause" do
4
+
5
+ it 'matches a valid when clause' do
6
+ when_clause = \
7
+ [:when_clause, [:bool_expr, [:bool_lit, true]], [:nop_st]]
8
+ (sexp_grammar[:when_clause] === when_clause).should be_true
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+ module Gisele::Language
3
+ describe ElsifFlattener do
4
+
5
+ def ast(source)
6
+ Gisele.ast(Gisele.parse(source.strip, :root => :if_st))
7
+ end
8
+
9
+ def rewrite(ast)
10
+ @rewrited = ElsifFlattener.call(ast)
11
+ end
12
+
13
+ after{
14
+ (sexp_grammar[:if_st] === @rewrited).should be_true
15
+ }
16
+
17
+ it 'rewrites a single if correctly' do
18
+ source = ast("if goodCond Task1 end")
19
+ rewrite(source).should eq(source)
20
+ end
21
+
22
+ it 'rewrites a if/else correctly' do
23
+ source = ast("if goodCond Task1 else Task2 end")
24
+ rewrite(source).should eq(source)
25
+ end
26
+
27
+ it 'rewrites a if/elsif correctly' do
28
+ source = ast("if good Task1 elsif bad Task2 end")
29
+ expected = ast("if good Task1 else if bad Task2 end end")
30
+ rewrite(source).should eq(expected)
31
+ end
32
+
33
+ it 'rewrites a if/elsif/else correctly' do
34
+ source = ast("if good Task1 elsif bad Task2 else Task3 end")
35
+ expected = ast("if good Task1 else if bad Task2 else Task3 end end")
36
+ rewrite(source).should eq(expected)
37
+ end
38
+
39
+ it 'rewrites a if/elsif/elsif/else correctly' do
40
+ source = ast(<<-EOF.strip)
41
+ if good Task1
42
+ elsif bad Task2
43
+ elsif none Task3
44
+ else Task4
45
+ end
46
+ EOF
47
+ expected = ast(<<-EOF.strip)
48
+ if good
49
+ Task1
50
+ else
51
+ if bad
52
+ Task2
53
+ else
54
+ if none
55
+ Task3
56
+ else
57
+ Task4
58
+ end
59
+ end
60
+ end
61
+ EOF
62
+ rewrite(source).should eq(expected)
63
+ end
64
+
65
+ it 'recurses by default' do
66
+ source = ast(<<-EOF.strip)
67
+ if goodCond
68
+ Task1
69
+ else
70
+ if bad
71
+ Task2
72
+ elsif middle
73
+ Task3
74
+ end
75
+ end
76
+ EOF
77
+ expected = ast(<<-EOF.strip)
78
+ if goodCond
79
+ Task1
80
+ else
81
+ if bad
82
+ Task2
83
+ else
84
+ if middle
85
+ Task3
86
+ end
87
+ end
88
+ end
89
+ EOF
90
+ rewrite(source).should eq(expected)
91
+ end
92
+
93
+ end
94
+ end