gisele-language 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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