gisele-language 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +26 -0
- data/LICENCE.md +22 -0
- data/Manifest.txt +13 -0
- data/README.md +7 -0
- data/Rakefile +11 -0
- data/gisele-language.gemspec +188 -0
- data/gisele-language.noespec +24 -0
- data/lib/gisele/language/ast/bool_and.rb +14 -0
- data/lib/gisele/language/ast/bool_expr.rb +22 -0
- data/lib/gisele/language/ast/bool_not.rb +14 -0
- data/lib/gisele/language/ast/bool_or.rb +14 -0
- data/lib/gisele/language/ast/case_st.rb +14 -0
- data/lib/gisele/language/ast/else_clause.rb +14 -0
- data/lib/gisele/language/ast/elsif_clause.rb +14 -0
- data/lib/gisele/language/ast/if_st.rb +14 -0
- data/lib/gisele/language/ast/node.rb +35 -0
- data/lib/gisele/language/ast/task_call_st.rb +14 -0
- data/lib/gisele/language/ast/var_ref.rb +14 -0
- data/lib/gisele/language/ast/when_clause.rb +14 -0
- data/lib/gisele/language/ast/while_st.rb +14 -0
- data/lib/gisele/language/grammar.citrus +236 -0
- data/lib/gisele/language/grammar.sexp.yml +83 -0
- data/lib/gisele/language/processors/elsif_flattener.rb +36 -0
- data/lib/gisele/language/processors/if_to_case.rb +65 -0
- data/lib/gisele/language/processors/scoping_helper.rb +32 -0
- data/lib/gisele/language/processors/sugar_removal.rb +17 -0
- data/lib/gisele/language/processors.rb +4 -0
- data/lib/gisele/language/syntax/bool_and.rb +14 -0
- data/lib/gisele/language/syntax/bool_expr.rb +14 -0
- data/lib/gisele/language/syntax/bool_lit.rb +14 -0
- data/lib/gisele/language/syntax/bool_not.rb +14 -0
- data/lib/gisele/language/syntax/bool_or.rb +14 -0
- data/lib/gisele/language/syntax/bool_paren.rb +14 -0
- data/lib/gisele/language/syntax/case_st.rb +19 -0
- data/lib/gisele/language/syntax/else_clause.rb +14 -0
- data/lib/gisele/language/syntax/elsif_clause.rb +16 -0
- data/lib/gisele/language/syntax/event_set.rb +15 -0
- data/lib/gisele/language/syntax/fluent_def.rb +18 -0
- data/lib/gisele/language/syntax/if_st.rb +18 -0
- data/lib/gisele/language/syntax/implicit_seq_st.rb +16 -0
- data/lib/gisele/language/syntax/node.rb +40 -0
- data/lib/gisele/language/syntax/par_st.rb +14 -0
- data/lib/gisele/language/syntax/seq_st.rb +14 -0
- data/lib/gisele/language/syntax/st_list.rb +14 -0
- data/lib/gisele/language/syntax/task_call_st.rb +14 -0
- data/lib/gisele/language/syntax/task_def.rb +18 -0
- data/lib/gisele/language/syntax/trackvar_def.rb +19 -0
- data/lib/gisele/language/syntax/unit_def.rb +14 -0
- data/lib/gisele/language/syntax/var_ref.rb +14 -0
- data/lib/gisele/language/syntax/when_clause.rb +16 -0
- data/lib/gisele/language/syntax/while_st.rb +16 -0
- data/lib/gisele/language.rb +31 -0
- data/lib/gisele-language/loader.rb +3 -0
- data/lib/gisele-language/version.rb +16 -0
- data/lib/gisele-language.rb +19 -0
- data/spec/fixtures/tasks/complete.gis +40 -0
- data/spec/fixtures/tasks/simple.ast +51 -0
- data/spec/fixtures/tasks/simple.gis +16 -0
- data/spec/language/ast/test_bool_expr.rb +50 -0
- data/spec/language/grammar_sexp/test_case_st.rb +20 -0
- data/spec/language/grammar_sexp/test_event_set.rb +14 -0
- data/spec/language/grammar_sexp/test_fluent_def.rb +18 -0
- data/spec/language/grammar_sexp/test_initially.rb +18 -0
- data/spec/language/grammar_sexp/test_nop_st.rb +10 -0
- data/spec/language/grammar_sexp/test_when_clause.rb +12 -0
- data/spec/language/processors/test_elsif_flattener.rb +94 -0
- data/spec/language/processors/test_if_to_case.rb +105 -0
- data/spec/language/processors/test_scoping_helper.rb +45 -0
- data/spec/language/syntax/grammar/test_bool_expr.rb +34 -0
- data/spec/language/syntax/grammar/test_boolean_literal.rb +17 -0
- data/spec/language/syntax/grammar/test_case_st.rb +60 -0
- data/spec/language/syntax/grammar/test_event.rb +18 -0
- data/spec/language/syntax/grammar/test_event_name.rb +21 -0
- data/spec/language/syntax/grammar/test_event_set.rb +26 -0
- data/spec/language/syntax/grammar/test_fluent_def.rb +21 -0
- data/spec/language/syntax/grammar/test_if_st.rb +21 -0
- data/spec/language/syntax/grammar/test_par_st.rb +11 -0
- data/spec/language/syntax/grammar/test_process_statement.rb +19 -0
- data/spec/language/syntax/grammar/test_seq_st.rb +11 -0
- data/spec/language/syntax/grammar/test_spaces.rb +19 -0
- data/spec/language/syntax/grammar/test_spacing.rb +17 -0
- data/spec/language/syntax/grammar/test_task_def.rb +35 -0
- data/spec/language/syntax/grammar/test_task_name.rb +19 -0
- data/spec/language/syntax/grammar/test_task_start_or_end.rb +17 -0
- data/spec/language/syntax/grammar/test_trackvar_def.rb +21 -0
- data/spec/language/syntax/grammar/test_unit_def.rb +29 -0
- data/spec/language/syntax/grammar/test_variable_name.rb +51 -0
- data/spec/language/syntax/grammar/test_when_clause.rb +21 -0
- data/spec/language/syntax/grammar/test_while_st.rb +11 -0
- data/spec/language/syntax/to_ast/test_bool_expr.rb +32 -0
- data/spec/language/syntax/to_ast/test_case_st.rb +47 -0
- data/spec/language/syntax/to_ast/test_else_clause.rb +13 -0
- data/spec/language/syntax/to_ast/test_elsif_clause.rb +15 -0
- data/spec/language/syntax/to_ast/test_event_set.rb +24 -0
- data/spec/language/syntax/to_ast/test_fluent_def.rb +26 -0
- data/spec/language/syntax/to_ast/test_if_st.rb +39 -0
- data/spec/language/syntax/to_ast/test_par_st.rb +12 -0
- data/spec/language/syntax/to_ast/test_seq_st.rb +12 -0
- data/spec/language/syntax/to_ast/test_task_call_st.rb +10 -0
- data/spec/language/syntax/to_ast/test_task_def.rb +44 -0
- data/spec/language/syntax/to_ast/test_trackvar_def.rb +26 -0
- data/spec/language/syntax/to_ast/test_unit_def.rb +28 -0
- data/spec/language/syntax/to_ast/test_var_ref.rb +12 -0
- data/spec/language/syntax/to_ast/test_when_clause.rb +15 -0
- data/spec/language/syntax/to_ast/test_while_st.rb +24 -0
- data/spec/language/test_syntax.rb +51 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/test_gisele-language.rb +8 -0
- data/tasks/gem.rake +73 -0
- data/tasks/spec_test.rake +71 -0
- 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,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,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,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,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,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
|