gobstones 0.0.2 → 0.0.3
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.
- checksums.yaml +5 -5
- data/.rubocop.yml +133 -0
- data/.rubocop_todo.yml +75 -0
- data/.simplecov +1 -3
- data/.tool-versions +1 -0
- data/.travis.yml +9 -2
- data/Gemfile +11 -5
- data/Gemfile.lock +65 -39
- data/README.md +8 -1
- data/Rakefile +1 -1
- data/bin/gobstones +1 -1
- data/gobstones.gemspec +12 -11
- data/lib/gobstones/cli/printer.rb +41 -28
- data/lib/gobstones/cli/runner.rb +50 -15
- data/lib/gobstones/extensions/all.rb +1 -1
- data/lib/gobstones/extensions/boolean.rb +1 -5
- data/lib/gobstones/extensions/{fixnum.rb → integer.rb} +2 -4
- data/lib/gobstones/extensions/string.rb +1 -3
- data/lib/gobstones/lang/all.rb +3 -3
- data/lib/gobstones/lang/commands/all.rb +11 -10
- data/lib/gobstones/lang/commands/boom.rb +26 -0
- data/lib/gobstones/lang/commands/command_block.rb +23 -23
- data/lib/gobstones/lang/commands/conditional.rb +26 -0
- data/lib/gobstones/lang/commands/if.rb +13 -0
- data/lib/gobstones/lang/commands/if_then_else.rb +26 -0
- data/lib/gobstones/lang/commands/ir_al_origen.rb +15 -0
- data/lib/gobstones/lang/commands/mover.rb +23 -0
- data/lib/gobstones/lang/commands/multiple_assignment.rb +34 -21
- data/lib/gobstones/lang/commands/poner.rb +31 -0
- data/lib/gobstones/lang/commands/procedure_call.rb +8 -8
- data/lib/gobstones/lang/commands/repeat_with.rb +69 -0
- data/lib/gobstones/lang/commands/sacar.rb +29 -0
- data/lib/gobstones/lang/commands/single_assignment.rb +15 -20
- data/lib/gobstones/lang/commands/skip.rb +15 -0
- data/lib/gobstones/lang/commands/vaciar_tablero.rb +15 -0
- data/lib/gobstones/lang/commands/while.rb +20 -0
- data/lib/gobstones/lang/definitions/definition.rb +16 -23
- data/lib/gobstones/lang/definitions/definition_call.rb +7 -15
- data/lib/gobstones/lang/definitions/function.rb +1 -7
- data/lib/gobstones/lang/definitions/main.rb +1 -8
- data/lib/gobstones/lang/definitions/no_return_statement.rb +2 -8
- data/lib/gobstones/lang/definitions/procedure.rb +1 -7
- data/lib/gobstones/lang/definitions/return_from_function.rb +6 -13
- data/lib/gobstones/lang/definitions/return_from_main.rb +15 -10
- data/lib/gobstones/lang/definitions/var_tuple.rb +10 -12
- data/lib/gobstones/lang/expressions/arithmetic_expressions.rb +17 -27
- data/lib/gobstones/lang/expressions/boolean_expressions.rb +4 -10
- data/lib/gobstones/lang/expressions/comparison_expressions.rb +0 -16
- data/lib/gobstones/lang/expressions/enclosed_by_parens_expression.rb +3 -5
- data/lib/gobstones/lang/expressions/expression.rb +18 -0
- data/lib/gobstones/lang/expressions/function_call.rb +9 -6
- data/lib/gobstones/lang/expressions/one_arg_expression.rb +8 -16
- data/lib/gobstones/lang/expressions/primitive_functions.rb +24 -16
- data/lib/gobstones/lang/expressions/two_arg_expression.rb +9 -16
- data/lib/gobstones/lang/expressions/type_bound_functions.rb +30 -25
- data/lib/gobstones/lang/expressions/var_name.rb +9 -13
- data/lib/gobstones/lang/literals/all.rb +3 -3
- data/lib/gobstones/lang/literals/{booleans.rb → boolean.rb} +24 -22
- data/lib/gobstones/lang/literals/{colors.rb → color.rb} +4 -14
- data/lib/gobstones/lang/literals/{directions.rb → direction.rb} +3 -13
- data/lib/gobstones/lang/literals/literal.rb +35 -27
- data/lib/gobstones/lang/literals/number.rb +6 -8
- data/lib/gobstones/lang/program.rb +9 -16
- data/lib/gobstones/modules/equality_definition.rb +23 -0
- data/lib/gobstones/parser/ast/ast.rb +48 -70
- data/lib/gobstones/parser/parse_error.rb +2 -7
- data/lib/gobstones/parser/treetop_parser.rb +9 -14
- data/lib/gobstones/runner/board.rb +12 -15
- data/lib/gobstones/runner/cell.rb +14 -20
- data/lib/gobstones/runner/errors/all.rb +1 -1
- data/lib/gobstones/runner/errors/boom_error.rb +0 -5
- data/lib/gobstones/runner/errors/definition_not_found_error.rb +7 -7
- data/lib/gobstones/runner/errors/empty_cell_error.rb +0 -5
- data/lib/gobstones/runner/errors/gobstones_runtime_error.rb +0 -5
- data/lib/gobstones/runner/errors/gobstones_type_error.rb +2 -7
- data/lib/gobstones/runner/errors/out_of_board_error.rb +0 -5
- data/lib/gobstones/runner/errors/undefined_variable_error.rb +6 -4
- data/lib/gobstones/runner/errors/wrong_arguments_error.rb +0 -5
- data/lib/gobstones/runner/execution_context.rb +16 -33
- data/lib/gobstones/runner/head.rb +17 -20
- data/lib/gobstones/runner/program_result.rb +12 -0
- data/lib/gobstones/type_check_result.rb +0 -4
- data/spec/lang/commands/boom_spec.rb +7 -0
- data/spec/lang/commands/command_block_spec.rb +15 -0
- data/spec/lang/commands/if_spec.rb +32 -0
- data/spec/lang/commands/if_then_else_spec.rb +19 -0
- data/spec/lang/commands/ir_al_origen_spec.rb +11 -0
- data/spec/lang/commands/mover_spec.rb +30 -0
- data/spec/lang/commands/multiple_assignment_spec.rb +39 -22
- data/spec/lang/commands/poner_spec.rb +27 -0
- data/spec/lang/commands/procedure_call_spec.rb +26 -28
- data/spec/lang/commands/procedure_spec.rb +32 -32
- data/spec/lang/commands/repeat_with_spec.rb +64 -0
- data/spec/lang/commands/sacar_spec.rb +32 -0
- data/spec/lang/commands/single_assignment_spec.rb +5 -6
- data/spec/lang/commands/skip_spec.rb +10 -0
- data/spec/lang/commands/vaciar_tablero_spec.rb +10 -0
- data/spec/lang/commands/while_spec.rb +39 -0
- data/spec/lang/definitions/main_spec.rb +34 -0
- data/spec/lang/definitions/no_return_statement_spec.rb +4 -5
- data/spec/lang/definitions/var_tuple_spec.rb +4 -7
- data/spec/lang/expressions/arithmetic_expressions_spec.rb +37 -64
- data/spec/lang/expressions/boolean_expressions_spec.rb +25 -34
- data/spec/lang/expressions/comparison_expressions_spec.rb +109 -155
- data/spec/lang/expressions/enclosed_by_parens_expression_spec.rb +3 -7
- data/spec/lang/expressions/function_call_spec.rb +24 -20
- data/spec/lang/expressions/primitive_functions_spec.rb +28 -39
- data/spec/lang/expressions/type_bound_functions_spec.rb +10 -18
- data/spec/lang/expressions/var_name_spec.rb +8 -12
- data/spec/lang/literals/{booleans_spec.rb → boolean_spec.rb} +3 -5
- data/spec/lang/literals/color_spec.rb +19 -0
- data/spec/lang/literals/direction_spec.rb +46 -0
- data/spec/lang/literals/{numbers_spec.rb → number_spec.rb} +3 -4
- data/spec/matchers/parse_matcher.rb +9 -11
- data/spec/parser/arithmetic_expressions_spec.rb +51 -61
- data/spec/parser/assignments_spec.rb +21 -31
- data/spec/parser/boolean_expressions_spec.rb +35 -43
- data/spec/parser/command_block_spec.rb +18 -20
- data/spec/parser/data_types_spec.rb +9 -19
- data/spec/parser/function_calls_spec.rb +19 -19
- data/spec/parser/function_definitions_spec.rb +17 -22
- data/spec/parser/gobstones_program_spec.rb +30 -30
- data/spec/parser/if_command_spec.rb +19 -28
- data/spec/parser/main_definition_spec.rb +13 -16
- data/spec/parser/nested_expressions_spec.rb +20 -24
- data/spec/parser/primitive_expressions_spec.rb +33 -38
- data/spec/parser/procedure_calls_spec.rb +17 -18
- data/spec/parser/procedure_definitions_spec.rb +12 -15
- data/spec/parser/repeat_with_command_spec.rb +10 -10
- data/spec/parser/simple_commands_spec.rb +23 -37
- data/spec/parser/treetop_parser_spec.rb +87 -83
- data/spec/parser/var_tuple_spec.rb +8 -12
- data/spec/parser/while_command_spec.rb +11 -14
- data/spec/runner/board_spec.rb +28 -33
- data/spec/runner/cell_spec.rb +21 -28
- data/spec/runner/execution_context_spec.rb +18 -35
- data/spec/runner/head_spec.rb +54 -60
- data/spec/spec_helper.rb +10 -1
- data/spec/support/board_assertions.rb +18 -0
- data/spec/{gobstones_lang_test_objects.rb → support/gobstones_lang_test_objects.rb} +6 -4
- data/spec/type_checker_spec.rb +19 -25
- metadata +80 -56
- data/.ruby-version +0 -1
- data/lib/gobstones/lang/commands/boom_cmd.rb +0 -31
- data/lib/gobstones/lang/commands/conditional_cmd.rb +0 -31
- data/lib/gobstones/lang/commands/if_cmd.rb +0 -38
- data/lib/gobstones/lang/commands/ir_al_origen_cmd.rb +0 -19
- data/lib/gobstones/lang/commands/mover_cmd.rb +0 -27
- data/lib/gobstones/lang/commands/poner_cmd.rb +0 -35
- data/lib/gobstones/lang/commands/repeat_with_cmd.rb +0 -77
- data/lib/gobstones/lang/commands/sacar_cmd.rb +0 -33
- data/lib/gobstones/lang/commands/skip_cmd.rb +0 -19
- data/lib/gobstones/lang/commands/vaciar_tablero_cmd.rb +0 -19
- data/lib/gobstones/lang/commands/while_cmd.rb +0 -25
- data/lib/gobstones/modules/equal_by_class.rb +0 -13
- data/spec/lang/commands/boom_cmd_spec.rb +0 -8
- data/spec/lang/commands/cmd_block_spec.rb +0 -21
- data/spec/lang/commands/if_cmd_spec.rb +0 -50
- data/spec/lang/commands/ir_al_origen_cmd_spec.rb +0 -16
- data/spec/lang/commands/mover_cmd_spec.rb +0 -36
- data/spec/lang/commands/poner_cmd_spec.rb +0 -28
- data/spec/lang/commands/repeat_with_cmd_spec.rb +0 -60
- data/spec/lang/commands/sacar_cmd_spec.rb +0 -35
- data/spec/lang/commands/skip_cmd_spec.rb +0 -12
- data/spec/lang/commands/vaciar_tablero_cmd_spec.rb +0 -14
- data/spec/lang/commands/while_cmd_spec.rb +0 -43
- data/spec/lang/literals/colors_spec.rb +0 -13
- data/spec/lang/literals/directions_spec.rb +0 -45
@@ -1,124 +1,113 @@
|
|
1
|
-
describe
|
2
|
-
|
1
|
+
RSpec.describe 'evaluating primitive functions' do
|
3
2
|
let(:context) { clean_context }
|
4
3
|
|
5
|
-
describe
|
6
|
-
|
7
|
-
it "evaluates correctly in a clean context" do
|
4
|
+
describe 'nroBolitas() function' do
|
5
|
+
it 'evaluates correctly in a clean context' do
|
8
6
|
expect(NroBolitas.new(negro).evaluate(context)).to eq(0.to_gbs_num)
|
9
7
|
end
|
10
8
|
|
11
|
-
it
|
9
|
+
it 'evaluates correctly in a context with some data' do
|
12
10
|
5.times { context.head.put negro }
|
11
|
+
|
13
12
|
expect(NroBolitas.new(negro).evaluate(context)).to eq(5.to_gbs_num)
|
14
13
|
end
|
15
|
-
|
16
14
|
end
|
17
15
|
|
18
|
-
describe
|
19
|
-
|
20
|
-
it "evaluates correctly in a clean context" do
|
16
|
+
describe 'hayBolitas() function' do
|
17
|
+
it 'evaluates correctly in a clean context' do
|
21
18
|
expect(HayBolitas.new(negro).evaluate(context)).to eq(false_value)
|
22
19
|
end
|
23
20
|
|
24
|
-
it
|
21
|
+
it 'evaluates correctly in a context with some data' do
|
25
22
|
context.head.put negro
|
23
|
+
|
26
24
|
expect(HayBolitas.new(negro).evaluate(context)).to eq(true_value)
|
27
25
|
end
|
28
|
-
|
29
26
|
end
|
30
27
|
|
31
|
-
describe
|
32
|
-
|
33
|
-
it "evaluates correctly in a clean context" do
|
28
|
+
describe 'puedeMover() function' do
|
29
|
+
it 'evaluates correctly in a clean context' do
|
34
30
|
expect(PuedeMover.new(oeste).evaluate(context)).to eq(false_value)
|
35
31
|
end
|
36
32
|
|
37
|
-
it
|
33
|
+
it 'evaluates correctly in a modified context' do
|
38
34
|
context.head.move(este)
|
35
|
+
|
39
36
|
expect(PuedeMover.new(oeste).evaluate(context)).to eq(true_value)
|
40
37
|
end
|
41
|
-
|
42
38
|
end
|
43
39
|
|
44
|
-
describe
|
45
|
-
|
46
|
-
it "evaluates correctly for numbers" do
|
40
|
+
describe 'siguiente() function' do
|
41
|
+
it 'evaluates correctly for numbers' do
|
47
42
|
expect(Siguiente.new(15.to_gbs_num).evaluate(context)).to eq(16.to_gbs_num)
|
48
43
|
end
|
49
44
|
|
50
|
-
it
|
45
|
+
it 'evaluates correctly for colors' do
|
51
46
|
expect(Siguiente.new(azul).evaluate(context)).to eq(negro)
|
52
47
|
expect(Siguiente.new(negro).evaluate(context)).to eq(rojo)
|
53
48
|
expect(Siguiente.new(rojo).evaluate(context)).to eq(verde)
|
54
49
|
expect(Siguiente.new(verde).evaluate(context)).to eq(azul)
|
55
50
|
end
|
56
51
|
|
57
|
-
it
|
52
|
+
it 'evaluates correctly for directions' do
|
58
53
|
expect(Siguiente.new(norte).evaluate(context)).to eq(este)
|
59
54
|
expect(Siguiente.new(este).evaluate(context)).to eq(sur)
|
60
55
|
expect(Siguiente.new(sur).evaluate(context)).to eq(oeste)
|
61
56
|
expect(Siguiente.new(oeste).evaluate(context)).to eq(norte)
|
62
57
|
end
|
63
58
|
|
64
|
-
it
|
59
|
+
it 'evaluates correctly for booleans' do
|
65
60
|
expect(Siguiente.new(true_value).evaluate(context)).to eq(false_value)
|
66
61
|
expect(Siguiente.new(false_value).evaluate(context)).to eq(true_value)
|
67
62
|
end
|
68
|
-
|
69
63
|
end
|
70
64
|
|
71
|
-
describe
|
72
|
-
|
73
|
-
it "evaluates correctly for numbers" do
|
65
|
+
describe 'previo() function' do
|
66
|
+
it 'evaluates correctly for numbers' do
|
74
67
|
expect(Previo.new(43.to_gbs_num).evaluate(context)).to eq(42.to_gbs_num)
|
75
68
|
end
|
76
69
|
|
77
|
-
it
|
70
|
+
it 'evaluates correctly for colors' do
|
78
71
|
expect(Previo.new(azul).evaluate(context)).to eq(verde)
|
79
72
|
expect(Previo.new(negro).evaluate(context)).to eq(azul)
|
80
73
|
expect(Previo.new(rojo).evaluate(context)).to eq(negro)
|
81
74
|
expect(Previo.new(verde).evaluate(context)).to eq(rojo)
|
82
75
|
end
|
83
76
|
|
84
|
-
it
|
77
|
+
it 'evaluates correctly for directions' do
|
85
78
|
expect(Previo.new(norte).evaluate(context)).to eq(oeste)
|
86
79
|
expect(Previo.new(este).evaluate(context)).to eq(norte)
|
87
80
|
expect(Previo.new(sur).evaluate(context)).to eq(este)
|
88
81
|
expect(Previo.new(oeste).evaluate(context)).to eq(sur)
|
89
82
|
end
|
90
83
|
|
91
|
-
it
|
84
|
+
it 'evaluates correctly for booleans' do
|
92
85
|
expect(Previo.new(true_value).evaluate(context)).to eq(false_value)
|
93
86
|
expect(Previo.new(false_value).evaluate(context)).to eq(true_value)
|
94
87
|
end
|
95
|
-
|
96
88
|
end
|
97
89
|
|
98
|
-
describe
|
99
|
-
|
100
|
-
it "evaluates correctly for numbers" do
|
90
|
+
describe 'opuesto() function' do
|
91
|
+
it 'evaluates correctly for numbers' do
|
101
92
|
expect(Opuesto.new(23.to_gbs_num).evaluate(context)).to eq(-23.to_gbs_num)
|
102
93
|
expect(Opuesto.new(-42.to_gbs_num).evaluate(context)).to eq(42.to_gbs_num)
|
103
94
|
end
|
104
95
|
|
105
|
-
it
|
96
|
+
it 'evaluates correctly for directions' do
|
106
97
|
expect(Opuesto.new(norte).evaluate(context)).to eq(sur)
|
107
98
|
expect(Opuesto.new(este).evaluate(context)).to eq(oeste)
|
108
99
|
expect(Opuesto.new(sur).evaluate(context)).to eq(norte)
|
109
100
|
expect(Opuesto.new(oeste).evaluate(context)).to eq(este)
|
110
101
|
end
|
111
102
|
|
112
|
-
it
|
103
|
+
it 'evaluates correctly for booleans' do
|
113
104
|
expect(Opuesto.new(true_value).evaluate(context)).to eq(false_value)
|
114
105
|
expect(Opuesto.new(false_value).evaluate(context)).to eq(true_value)
|
115
106
|
end
|
116
107
|
|
117
|
-
it
|
108
|
+
it 'fails when evaluating for colors' do
|
118
109
|
expect { Opuesto.new(verde).evaluate(context) }.
|
119
110
|
to raise_error(GobstonesTypeError, "colors don't have opposite")
|
120
111
|
end
|
121
|
-
|
122
112
|
end
|
123
|
-
|
124
113
|
end
|
@@ -1,39 +1,31 @@
|
|
1
|
-
describe
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
it "evaluates minBool() to False" do
|
1
|
+
RSpec.describe 'type bound functions' do
|
2
|
+
describe 'for booleans' do
|
3
|
+
it 'evaluates minBool() to False' do
|
6
4
|
expect(MinBool.new.evaluate).to eq(false_value)
|
7
5
|
end
|
8
6
|
|
9
|
-
it
|
7
|
+
it 'evaluates maxBool() to True' do
|
10
8
|
expect(MaxBool.new.evaluate).to eq(true_value)
|
11
9
|
end
|
12
|
-
|
13
10
|
end
|
14
11
|
|
15
|
-
describe
|
16
|
-
|
17
|
-
it "evaluates minColor() to Azul" do
|
12
|
+
describe 'for colors' do
|
13
|
+
it 'evaluates minColor() to Azul' do
|
18
14
|
expect(MinColor.new.evaluate).to eq(azul)
|
19
15
|
end
|
20
16
|
|
21
|
-
it
|
17
|
+
it 'evaluates maxColor() to Verde' do
|
22
18
|
expect(MaxColor.new.evaluate).to eq(verde)
|
23
19
|
end
|
24
|
-
|
25
20
|
end
|
26
21
|
|
27
|
-
describe
|
28
|
-
|
29
|
-
it "evaluates minDir() to Norte" do
|
22
|
+
describe 'for directions' do
|
23
|
+
it 'evaluates minDir() to Norte' do
|
30
24
|
expect(MinDir.new.evaluate).to eq(norte)
|
31
25
|
end
|
32
26
|
|
33
|
-
it
|
27
|
+
it 'evaluates maxDir() to Oeste' do
|
34
28
|
expect(MaxDir.new.evaluate).to eq(oeste)
|
35
29
|
end
|
36
|
-
|
37
30
|
end
|
38
|
-
|
39
31
|
end
|
@@ -1,28 +1,24 @@
|
|
1
|
-
describe VarName do
|
2
|
-
|
1
|
+
RSpec.describe VarName do
|
3
2
|
let(:context) { clean_context }
|
4
3
|
let(:variable_name) { 'var'.to_var_name }
|
5
4
|
|
6
|
-
it
|
5
|
+
it 'returns the associated value if it was defined in the context' do
|
7
6
|
context.set variable_name, 42.to_gbs_num
|
7
|
+
|
8
8
|
expect(variable_name.evaluate(context)).to eq(42.to_gbs_num)
|
9
9
|
end
|
10
10
|
|
11
|
-
it
|
12
|
-
expect { variable_name.evaluate context }
|
13
|
-
.to raise_error(UndefinedVariableError)
|
11
|
+
it 'raises an error if there is no definition in context' do
|
12
|
+
expect { variable_name.evaluate context }.to raise_error(UndefinedVariableError)
|
14
13
|
end
|
15
14
|
|
16
|
-
describe
|
17
|
-
|
15
|
+
describe '#named?' do
|
18
16
|
it "is named 'var'" do
|
19
|
-
expect(variable_name.named?
|
17
|
+
expect(variable_name.named?('var')).to be(true)
|
20
18
|
end
|
21
19
|
|
22
20
|
it "is not named 'blah'" do
|
23
|
-
expect(variable_name.named?
|
21
|
+
expect(variable_name.named?('blah')).to be(false)
|
24
22
|
end
|
25
|
-
|
26
23
|
end
|
27
|
-
|
28
24
|
end
|
@@ -1,11 +1,9 @@
|
|
1
|
-
describe Boolean do
|
2
|
-
|
3
|
-
it "evaluates true to itself" do
|
1
|
+
RSpec.describe Boolean do
|
2
|
+
it 'evaluates true to itself' do
|
4
3
|
expect(true_value.evaluate).to eq(true_value)
|
5
4
|
end
|
6
5
|
|
7
|
-
it
|
6
|
+
it 'evaluates false to itself' do
|
8
7
|
expect(false_value.evaluate).to eq(false_value)
|
9
8
|
end
|
10
|
-
|
11
9
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
RSpec.describe Color do
|
2
|
+
let(:all) { described_class.all.map(&:new) }
|
3
|
+
|
4
|
+
it 'includes Azul, Negro, Rojo and Verde' do
|
5
|
+
expect(all).to contain_exactly(azul, negro, rojo, verde)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'includes all color classes in the order specification' do
|
9
|
+
expect(described_class.all).to match_array(described_class.order)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'evaluates any color to itself' do
|
13
|
+
all.each { |color| expect(color.evaluate).to eq(color) }
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns the string representation' do
|
17
|
+
expect(all.map(&:to_s)).to eq(%w[Azul Negro Rojo Verde])
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
RSpec.describe Direction do
|
2
|
+
let(:all) { described_class.all.map(&:new) }
|
3
|
+
|
4
|
+
it 'includes Norte, Este, Sur and Oeste' do
|
5
|
+
expect(all.include?(norte)).to be(true)
|
6
|
+
expect(all.include?(este)).to be(true)
|
7
|
+
expect(all.include?(sur)).to be(true)
|
8
|
+
expect(all.include?(oeste)).to be(true)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'includes all direction classes in the order specification' do
|
12
|
+
expect(described_class.all).to match_array(described_class.order)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'evaluates any direction to itself' do
|
16
|
+
all.each { |dir| expect(dir.evaluate).to eq(dir) }
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns the string representation' do
|
20
|
+
expect(all.map(&:to_s)).to eq(%w[Norte Sur Este Oeste])
|
21
|
+
end
|
22
|
+
|
23
|
+
describe Norte do
|
24
|
+
it 'returns Sur as the opposite direction' do
|
25
|
+
expect(norte.opposite).to eq(sur)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe Este do
|
30
|
+
it 'returns Oeste as the opposite direction' do
|
31
|
+
expect(este.opposite).to eq(oeste)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe Sur do
|
36
|
+
it 'returns Norte as the opposite direction' do
|
37
|
+
expect(sur.opposite).to eq(norte)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe Oeste do
|
42
|
+
it 'returns Este as the opposite direction' do
|
43
|
+
expect(oeste.opposite).to eq(este)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -4,7 +4,6 @@ require 'gobstones/lang/program'
|
|
4
4
|
PARSER = Gobstones::Parser::TreetopParser.new
|
5
5
|
|
6
6
|
RSpec::Matchers.define :be_parsed_as do |grammar_elem|
|
7
|
-
|
8
7
|
chain :and_fail do
|
9
8
|
@expect_parser_results = false
|
10
9
|
end
|
@@ -15,14 +14,14 @@ RSpec::Matchers.define :be_parsed_as do |grammar_elem|
|
|
15
14
|
end
|
16
15
|
|
17
16
|
match do |actual|
|
18
|
-
valid_nodes = [
|
17
|
+
valid_nodes = %i[program definition main expression command var_tuple]
|
19
18
|
fail 'wrong expectation' if @expect_parser_results.nil?
|
20
19
|
fail 'grammar elem not supported' unless valid_nodes.include?(grammar_elem)
|
21
20
|
|
22
21
|
begin
|
23
22
|
parse send("#{grammar_elem}_code_to_program", actual)
|
24
23
|
@value == send("#{grammar_elem}_node_to_program", @expected)
|
25
|
-
rescue Gobstones::Parser::ParseError
|
24
|
+
rescue Gobstones::Parser::ParseError
|
26
25
|
!@expect_parser_results
|
27
26
|
end
|
28
27
|
end
|
@@ -40,7 +39,7 @@ RSpec::Matchers.define :be_parsed_as do |grammar_elem|
|
|
40
39
|
end
|
41
40
|
|
42
41
|
def main_node_to_program(node)
|
43
|
-
Program.new
|
42
|
+
Program.new(no_definitions, node)
|
44
43
|
end
|
45
44
|
|
46
45
|
def definition_code_to_program(code)
|
@@ -48,7 +47,7 @@ RSpec::Matchers.define :be_parsed_as do |grammar_elem|
|
|
48
47
|
end
|
49
48
|
|
50
49
|
def definition_node_to_program(node)
|
51
|
-
Program.new
|
50
|
+
Program.new([node], Main.new(empty_body, no_return_statement))
|
52
51
|
end
|
53
52
|
|
54
53
|
def expression_code_to_program(code)
|
@@ -56,8 +55,8 @@ RSpec::Matchers.define :be_parsed_as do |grammar_elem|
|
|
56
55
|
end
|
57
56
|
|
58
57
|
def expression_node_to_program(node)
|
59
|
-
assign = SingleAssignment.new
|
60
|
-
main_node_to_program
|
58
|
+
assign = SingleAssignment.new('x'.to_var_name, node)
|
59
|
+
main_node_to_program(Main.new(CommandBlock.with_just(assign), no_return_statement))
|
61
60
|
end
|
62
61
|
|
63
62
|
def command_code_to_program(code)
|
@@ -65,7 +64,7 @@ RSpec::Matchers.define :be_parsed_as do |grammar_elem|
|
|
65
64
|
end
|
66
65
|
|
67
66
|
def command_node_to_program(node)
|
68
|
-
main_node_to_program
|
67
|
+
main_node_to_program(Main.new(CommandBlock.with_just(node), no_return_statement))
|
69
68
|
end
|
70
69
|
|
71
70
|
def var_tuple_code_to_program(code)
|
@@ -73,11 +72,10 @@ RSpec::Matchers.define :be_parsed_as do |grammar_elem|
|
|
73
72
|
end
|
74
73
|
|
75
74
|
def var_tuple_node_to_program(node)
|
76
|
-
Program.new
|
75
|
+
Program.new(no_definitions, Main.new(empty_body, ReturnFromMain.new(node)))
|
77
76
|
end
|
78
77
|
|
79
78
|
def parse(code)
|
80
|
-
@value = PARSER.parse
|
79
|
+
@value = PARSER.parse(code)
|
81
80
|
end
|
82
|
-
|
83
81
|
end
|
@@ -1,129 +1,119 @@
|
|
1
|
-
describe
|
2
|
-
|
1
|
+
RSpec.describe 'parsing arithmetic expressions' do
|
3
2
|
let(:a) { 'a'.to_var_name }
|
4
3
|
let(:b) { 'b'.to_var_name }
|
5
4
|
let(:c) { 'c'.to_var_name }
|
6
5
|
let(:d) { 'd'.to_var_name }
|
7
6
|
|
8
|
-
describe
|
9
|
-
|
10
|
-
|
11
|
-
sum = Add.new a, b
|
7
|
+
describe 'addition and subtraction' do
|
8
|
+
it 'parses a + expression' do
|
9
|
+
sum = Add.new(a, b)
|
12
10
|
|
13
11
|
expect('a+b').to be_parsed_as(:expression).and_return(sum)
|
14
12
|
expect('a + b').to be_parsed_as(:expression).and_return(sum)
|
15
13
|
end
|
16
14
|
|
17
|
-
it
|
18
|
-
sum_ab = Add.new
|
19
|
-
total = Add.new
|
15
|
+
it 'parses a nested + expression, associating to left' do
|
16
|
+
sum_ab = Add.new(a, b)
|
17
|
+
total = Add.new(sum_ab, c)
|
20
18
|
|
21
19
|
expect('a + b + c').to be_parsed_as(:expression).and_return(total)
|
22
20
|
end
|
23
21
|
|
24
|
-
it
|
25
|
-
sub = Sub.new
|
22
|
+
it 'parses a - expression' do
|
23
|
+
sub = Sub.new(a, b)
|
26
24
|
|
27
25
|
expect('a-b').to be_parsed_as(:expression).and_return(sub)
|
28
26
|
expect('a - b').to be_parsed_as(:expression).and_return(sub)
|
29
27
|
end
|
30
28
|
|
31
|
-
it
|
32
|
-
sum_ab = Add.new
|
33
|
-
total = Sub.new
|
29
|
+
it 'parses a nested expression with + and -, associating to left' do
|
30
|
+
sum_ab = Add.new(a, b)
|
31
|
+
total = Sub.new(sum_ab, c)
|
34
32
|
|
35
33
|
expect('a + b - c').to be_parsed_as(:expression).and_return(total)
|
36
34
|
end
|
37
|
-
|
38
35
|
end
|
39
36
|
|
40
|
-
describe
|
41
|
-
|
42
|
-
|
43
|
-
mul = Mul.new a, b
|
37
|
+
describe 'multiplication, division, modulus and power' do
|
38
|
+
it 'parses a * expression' do
|
39
|
+
mul = Mul.new(a, b)
|
44
40
|
|
45
41
|
expect('a*b').to be_parsed_as(:expression).and_return(mul)
|
46
42
|
expect('a * b').to be_parsed_as(:expression).and_return(mul)
|
47
43
|
end
|
48
44
|
|
49
|
-
it
|
50
|
-
mul_ab = Mul.new
|
51
|
-
total = Mul.new
|
45
|
+
it 'parses a nested * expression' do
|
46
|
+
mul_ab = Mul.new(a, b)
|
47
|
+
total = Mul.new(mul_ab, c)
|
52
48
|
|
53
49
|
expect('a * b * c').to be_parsed_as(:expression).and_return(total)
|
54
50
|
end
|
55
51
|
|
56
|
-
it
|
57
|
-
div = Div.new
|
52
|
+
it 'parses a div expression' do
|
53
|
+
div = Div.new(a, b)
|
58
54
|
|
59
55
|
expect('a div b').to be_parsed_as(:expression).and_return(div)
|
60
56
|
expect('a div b').to be_parsed_as(:expression).and_return(div)
|
61
57
|
end
|
62
58
|
|
63
|
-
it
|
64
|
-
mod = Mod.new
|
59
|
+
it 'parses a mod expression' do
|
60
|
+
mod = Mod.new(a, b)
|
65
61
|
|
66
62
|
expect('a mod b').to be_parsed_as(:expression).and_return(mod)
|
67
63
|
expect('a mod b').to be_parsed_as(:expression).and_return(mod)
|
68
64
|
end
|
69
65
|
|
70
|
-
it
|
71
|
-
pow = Pow.new
|
66
|
+
it 'parses a power expression' do
|
67
|
+
pow = Pow.new(a, b)
|
72
68
|
|
73
69
|
expect('a^b').to be_parsed_as(:expression).and_return(pow)
|
74
70
|
expect('a ^ b').to be_parsed_as(:expression).and_return(pow)
|
75
71
|
end
|
76
72
|
|
77
|
-
it
|
78
|
-
pow_ab = Pow.new
|
79
|
-
pow_abc = Pow.new
|
80
|
-
pow_abcd = Pow.new
|
73
|
+
it 'parses a nested power expression, associating left' do
|
74
|
+
pow_ab = Pow.new(a, b)
|
75
|
+
pow_abc = Pow.new(pow_ab, c)
|
76
|
+
pow_abcd = Pow.new(pow_abc, d)
|
81
77
|
|
82
78
|
expect('a ^ b ^ c ^ d').to be_parsed_as(:expression).and_return(pow_abcd)
|
83
79
|
end
|
84
|
-
|
85
80
|
end
|
86
81
|
|
87
|
-
describe
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
add = Add.new sub, d
|
82
|
+
describe 'complex arithmetic expressions (without parentheses)' do
|
83
|
+
it 'parses using precedence of + and - over *' do
|
84
|
+
mul = Mul.new(b, c)
|
85
|
+
sub = Sub.new(a, mul)
|
86
|
+
add = Add.new(sub, d)
|
93
87
|
|
94
88
|
expect('a - b * c + d').to be_parsed_as(:expression).and_return(add)
|
95
89
|
end
|
96
90
|
|
97
|
-
it
|
98
|
-
div = Div.new
|
99
|
-
mod = Mod.new
|
100
|
-
inner_mul = Mul.new
|
101
|
-
outer_mul = Mul.new
|
91
|
+
it 'parses using precedence of * over div and mod' do
|
92
|
+
div = Div.new(a, b)
|
93
|
+
mod = Mod.new(a, c)
|
94
|
+
inner_mul = Mul.new(div, mod)
|
95
|
+
outer_mul = Mul.new(inner_mul, d)
|
102
96
|
|
103
|
-
expect('a div b * a mod c * d').
|
104
|
-
to be_parsed_as(:expression).and_return(outer_mul)
|
97
|
+
expect('a div b * a mod c * d').to be_parsed_as(:expression).and_return(outer_mul)
|
105
98
|
end
|
106
99
|
|
107
|
-
it
|
108
|
-
pow_ab = Pow.new
|
109
|
-
pow_cd = Pow.new
|
110
|
-
div = Div.new
|
100
|
+
it 'parses using precedence of div and mod over ^' do
|
101
|
+
pow_ab = Pow.new(a, b)
|
102
|
+
pow_cd = Pow.new(c, d)
|
103
|
+
div = Div.new(pow_ab, pow_cd)
|
111
104
|
|
112
105
|
expect('a^b div c^d').to be_parsed_as(:expression).and_return(div)
|
113
106
|
end
|
114
107
|
|
115
|
-
it
|
116
|
-
pow = Pow.new
|
117
|
-
mod = Mod.new
|
118
|
-
div = Div.new
|
119
|
-
mul = Mul.new
|
120
|
-
add = Add.new
|
121
|
-
sub = Sub.new
|
108
|
+
it 'parses an expression with all kind of operators' do
|
109
|
+
pow = Pow.new(b, c)
|
110
|
+
mod = Mod.new(a, pow)
|
111
|
+
div = Div.new(d, b)
|
112
|
+
mul = Mul.new(a, div)
|
113
|
+
add = Add.new(mod, mul)
|
114
|
+
sub = Sub.new(add, c)
|
122
115
|
|
123
|
-
expect('a mod b ^ c + a * d div b - c').
|
124
|
-
to be_parsed_as(:expression).and_return(sub)
|
116
|
+
expect('a mod b ^ c + a * d div b - c').to be_parsed_as(:expression).and_return(sub)
|
125
117
|
end
|
126
|
-
|
127
118
|
end
|
128
|
-
|
129
119
|
end
|