gobstones 0.0.1.1 → 0.0.2

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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -3
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +1 -1
  5. data/CHANGELOG +22 -2
  6. data/Gemfile +3 -3
  7. data/Gemfile.lock +32 -27
  8. data/bin/gobstones +1 -1
  9. data/examples/.gitkeep +0 -0
  10. data/gobstones.gemspec +2 -2
  11. data/lib/gobstones/cli/board_template +1 -1
  12. data/lib/gobstones/cli/printer.rb +1 -1
  13. data/lib/gobstones/cli/runner.rb +8 -2
  14. data/lib/gobstones/extensions/all.rb +2 -1
  15. data/lib/gobstones/extensions/boolean.rb +1 -1
  16. data/lib/gobstones/extensions/fixnum.rb +1 -1
  17. data/lib/gobstones/extensions/string.rb +9 -0
  18. data/lib/gobstones/lang/all.rb +1 -1
  19. data/lib/gobstones/lang/commands/all.rb +3 -2
  20. data/lib/gobstones/lang/commands/boom_cmd.rb +6 -3
  21. data/lib/gobstones/lang/commands/command_block.rb +1 -1
  22. data/lib/gobstones/lang/commands/conditional_cmd.rb +5 -1
  23. data/lib/gobstones/lang/commands/ir_al_origen_cmd.rb +1 -1
  24. data/lib/gobstones/lang/commands/mover_cmd.rb +4 -2
  25. data/lib/gobstones/lang/commands/multiple_assignment.rb +35 -0
  26. data/lib/gobstones/lang/commands/poner_cmd.rb +8 -4
  27. data/lib/gobstones/lang/commands/procedure_call.rb +1 -9
  28. data/lib/gobstones/lang/commands/repeat_with_cmd.rb +10 -6
  29. data/lib/gobstones/lang/commands/sacar_cmd.rb +9 -7
  30. data/lib/gobstones/lang/commands/{assignments.rb → single_assignment.rb} +5 -3
  31. data/lib/gobstones/lang/commands/skip_cmd.rb +2 -2
  32. data/lib/gobstones/lang/commands/vaciar_tablero_cmd.rb +1 -1
  33. data/lib/gobstones/lang/commands/while_cmd.rb +1 -1
  34. data/lib/gobstones/lang/definitions/all.rb +1 -1
  35. data/lib/gobstones/lang/definitions/definition.rb +47 -5
  36. data/lib/gobstones/lang/definitions/definition_call.rb +17 -5
  37. data/lib/gobstones/lang/definitions/function.rb +9 -0
  38. data/lib/gobstones/lang/definitions/main.rb +1 -1
  39. data/lib/gobstones/lang/definitions/no_return_statement.rb +7 -3
  40. data/lib/gobstones/lang/definitions/procedure.rb +5 -20
  41. data/lib/gobstones/lang/definitions/return_from_function.rb +12 -2
  42. data/lib/gobstones/lang/definitions/return_from_main.rb +5 -1
  43. data/lib/gobstones/lang/definitions/var_tuple.rb +13 -1
  44. data/lib/gobstones/lang/expressions/all.rb +1 -1
  45. data/lib/gobstones/lang/expressions/arithmetic_expressions.rb +1 -1
  46. data/lib/gobstones/lang/expressions/boolean_expressions.rb +3 -2
  47. data/lib/gobstones/lang/expressions/enclosed_by_parens_expression.rb +17 -0
  48. data/lib/gobstones/lang/expressions/function_call.rb +1 -1
  49. data/lib/gobstones/lang/expressions/one_arg_expression.rb +16 -4
  50. data/lib/gobstones/lang/expressions/primitive_functions.rb +18 -12
  51. data/lib/gobstones/lang/expressions/two_arg_expression.rb +7 -3
  52. data/lib/gobstones/lang/expressions/type_bound_functions.rb +1 -1
  53. data/lib/gobstones/lang/expressions/var_name.rb +9 -3
  54. data/lib/gobstones/lang/literals/all.rb +1 -1
  55. data/lib/gobstones/lang/literals/colors.rb +1 -1
  56. data/lib/gobstones/lang/literals/literal.rb +31 -21
  57. data/lib/gobstones/lang/literals/number.rb +1 -1
  58. data/lib/gobstones/lang/program.rb +13 -4
  59. data/lib/gobstones/modules/equal_by_class.rb +1 -1
  60. data/lib/gobstones/parser/ast/ast.rb +12 -8
  61. data/lib/gobstones/parser/grammar/gobstones.treetop +4 -4
  62. data/lib/gobstones/parser/parse_error.rb +1 -1
  63. data/lib/gobstones/runner/all.rb +1 -2
  64. data/lib/gobstones/runner/board.rb +13 -4
  65. data/lib/gobstones/runner/cell.rb +10 -0
  66. data/lib/gobstones/runner/errors/all.rb +1 -1
  67. data/lib/gobstones/runner/errors/definition_not_found_error.rb +1 -1
  68. data/lib/gobstones/runner/execution_context.rb +66 -16
  69. data/lib/gobstones/runner/head.rb +17 -3
  70. data/spec/gobstones_lang_test_objects.rb +75 -0
  71. data/spec/lang/commands/boom_cmd_spec.rb +3 -3
  72. data/spec/lang/commands/cmd_block_spec.rb +14 -14
  73. data/spec/lang/commands/if_cmd_spec.rb +21 -20
  74. data/spec/lang/commands/ir_al_origen_cmd_spec.rb +3 -3
  75. data/spec/lang/commands/mover_cmd_spec.rb +12 -14
  76. data/spec/lang/commands/multiple_assignment_spec.rb +37 -0
  77. data/spec/lang/commands/poner_cmd_spec.rb +13 -14
  78. data/spec/lang/commands/procedure_call_spec.rb +19 -24
  79. data/spec/lang/commands/procedure_spec.rb +32 -36
  80. data/spec/lang/commands/repeat_with_cmd_spec.rb +39 -20
  81. data/spec/lang/commands/sacar_cmd_spec.rb +17 -16
  82. data/spec/lang/commands/single_assignment_spec.rb +13 -0
  83. data/spec/lang/commands/skip_cmd_spec.rb +2 -2
  84. data/spec/lang/commands/vaciar_tablero_cmd_spec.rb +7 -6
  85. data/spec/lang/commands/while_cmd_spec.rb +21 -15
  86. data/spec/lang/definitions/no_return_statement_spec.rb +10 -0
  87. data/spec/lang/definitions/var_tuple_spec.rb +16 -0
  88. data/spec/lang/expressions/arithmetic_expressions_spec.rb +15 -15
  89. data/spec/lang/expressions/boolean_expressions_spec.rb +35 -25
  90. data/spec/lang/expressions/comparison_expressions_spec.rb +25 -28
  91. data/spec/lang/expressions/enclosed_by_parens_expression_spec.rb +11 -0
  92. data/spec/lang/expressions/function_call_spec.rb +29 -0
  93. data/spec/lang/expressions/primitive_functions_spec.rb +60 -62
  94. data/spec/lang/expressions/type_bound_functions_spec.rb +13 -13
  95. data/spec/lang/expressions/var_name_spec.rb +20 -8
  96. data/spec/lang/literals/booleans_spec.rb +5 -7
  97. data/spec/lang/literals/colors_spec.rb +4 -4
  98. data/spec/lang/literals/directions_spec.rb +12 -12
  99. data/spec/lang/literals/numbers_spec.rb +2 -2
  100. data/spec/matchers/parse_matcher.rb +9 -10
  101. data/spec/parser/arithmetic_expressions_spec.rb +19 -19
  102. data/spec/parser/assignments_spec.rb +24 -10
  103. data/spec/parser/boolean_expressions_spec.rb +18 -18
  104. data/spec/parser/command_block_spec.rb +17 -19
  105. data/spec/parser/data_types_spec.rb +23 -23
  106. data/spec/parser/function_calls_spec.rb +13 -12
  107. data/spec/parser/function_definitions_spec.rb +13 -18
  108. data/spec/parser/gobstones_program_spec.rb +15 -15
  109. data/spec/parser/if_command_spec.rb +13 -12
  110. data/spec/parser/main_definition_spec.rb +12 -12
  111. data/spec/parser/nested_expressions_spec.rb +16 -20
  112. data/spec/parser/primitive_expressions_spec.rb +27 -33
  113. data/spec/parser/procedure_calls_spec.rb +12 -12
  114. data/spec/parser/procedure_definitions_spec.rb +10 -16
  115. data/spec/parser/repeat_with_command_spec.rb +7 -10
  116. data/spec/parser/simple_commands_spec.rb +10 -10
  117. data/spec/parser/treetop_parser_spec.rb +11 -10
  118. data/spec/parser/var_tuple_spec.rb +7 -11
  119. data/spec/parser/while_command_spec.rb +9 -9
  120. data/spec/runner/board_spec.rb +23 -27
  121. data/spec/runner/cell_spec.rb +34 -38
  122. data/spec/runner/execution_context_spec.rb +38 -24
  123. data/spec/runner/head_spec.rb +54 -63
  124. data/spec/spec_helper.rb +4 -1
  125. data/spec/type_checker_spec.rb +13 -13
  126. metadata +33 -18
  127. data/lib/gobstones/lang/expressions/parentheses_expression.rb +0 -13
  128. data/spec/lang/commands/assignments_spec.rb +0 -13
@@ -1,18 +1,16 @@
1
1
  describe Mover do
2
2
 
3
- let(:context) { ProgramExecutionContext.for double('GobstonesProgram') }
4
- let(:north) { Norte.new }
5
- let(:south) { Sur.new }
3
+ let(:context) { clean_context }
6
4
 
7
- it "should run" do
8
- Mover.new(north).evaluate(context)
5
+ it "moves the head to the specified direction when evaluating" do
6
+ Mover.new(norte).evaluate(context)
9
7
 
10
8
  expect(context.head.x_pos).to eq(0)
11
9
  expect(context.head.y_pos).to eq(1)
12
10
  end
13
11
 
14
- it "should undo" do
15
- cmd = Mover.new(north)
12
+ it "undoes the given movement" do
13
+ cmd = Mover.new norte
16
14
 
17
15
  cmd.evaluate context
18
16
  cmd.undo context
@@ -21,18 +19,18 @@ describe Mover do
21
19
  expect(context.head.y_pos).to eq(0)
22
20
  end
23
21
 
24
- it "should return opposite cmd" do
25
- expect(Mover.new(north).opposite).to eq(Mover.new(south))
22
+ it "returns the opposite command" do
23
+ expect(Mover.new(norte).opposite).to eq(Mover.new(sur))
26
24
  end
27
25
 
28
- it "should fail if types don't match" do
29
- expect { Mover.new(Verde.new).evaluate(context) }.
26
+ it "fails if the argument is not a direction" do
27
+ expect { Mover.new(verde).evaluate(context) }.
30
28
  to raise_error(GobstonesTypeError, /is not a direction/)
31
29
  end
32
30
 
33
- it "should fail when out of board" do
34
- expect { Mover.new(south).evaluate(context) }.
31
+ it "fails when the resulting position is out of board" do
32
+ expect { Mover.new(sur).evaluate(context) }.
35
33
  to raise_error(OutOfBoardError)
36
34
  end
37
35
 
38
- end
36
+ end
@@ -0,0 +1,37 @@
1
+ describe MultipleAssignment do
2
+
3
+ let(:my_function_return) { ReturnFromFunction.new [42.to_gbs_num, verde, MinDir.new] }
4
+ let(:my_function_def) { Function.new 'myFunction', no_arguments, empty_body, my_function_return }
5
+ let(:program) { Program.new [my_function_def], no_return_statement }
6
+ let(:context) { program_context_for program }
7
+ let(:a) { 'a'.to_var_name }
8
+ let(:b) { 'b'.to_var_name }
9
+ let(:c) { 'c'.to_var_name }
10
+
11
+ context "success" do
12
+
13
+ it "evaluates and set all the variables with the return values of a function call" do
14
+ var_tuple = VarTuple.new [a, b, c]
15
+ function_call = FunctionCall.new 'myFunction', []
16
+ assign = MultipleAssignment.new var_tuple, function_call
17
+ assign.evaluate context
18
+ expect(context.has_variable_named?('a')).to be true
19
+ expect(context.get(a)).to eq(42.to_gbs_num)
20
+ expect(context.has_variable_named?('b')).to be true
21
+ expect(context.get(b)).to eq(verde)
22
+ expect(context.has_variable_named?('c')).to be true
23
+ expect(context.get(c)).to eq(norte)
24
+ end
25
+
26
+ end
27
+
28
+ context "failure" do
29
+
30
+ it "fails if there are more variables to be assigned on the left"
31
+
32
+ it "fails if there are more things to assign on the right"
33
+
34
+ it "fails if the expression on the right is not a function call"
35
+
36
+ end
37
+ end
@@ -1,29 +1,28 @@
1
1
  describe Poner do
2
2
 
3
- let(:context) { ProgramExecutionContext.for double('GobstonesProgram') }
4
- let(:green) { Verde.new }
3
+ let(:context) { clean_context }
5
4
 
6
- it "should execute" do
7
- Poner.new(green).evaluate(context)
5
+ it "puts a ball of the given color in the current cell when evaluating" do
6
+ Poner.new(verde).evaluate(context)
8
7
 
9
- expect(context.head.number_of_balls(green)).to eq(1)
8
+ expect(context.head.number_of_balls(verde)).to eq(1)
10
9
  end
11
10
 
12
- it "should undo" do
13
- context.head.put green
11
+ it "undoes the command" do
12
+ context.head.put verde
14
13
 
15
- Poner.new(green).undo context
14
+ Poner.new(verde).undo context
16
15
 
17
- expect(context.head.number_of_balls(green)).to eq(0)
16
+ expect(context.head.number_of_balls(verde)).to eq(0)
18
17
  end
19
18
 
20
- it "should return the opposite cmd" do
21
- expect(Poner.new(green).opposite).to eq(Sacar.new(green))
19
+ it "returns the opposite command" do
20
+ expect(Poner.new(verde).opposite).to eq(Sacar.new(verde))
22
21
  end
23
22
 
24
- it "should fail if types don't match" do
25
- expect { Poner.new(Norte.new).evaluate(context) }.
23
+ it "fails if the argument is not a color" do
24
+ expect { Poner.new(norte).evaluate(context) }.
26
25
  to raise_error(GobstonesTypeError, /is not a color/)
27
26
  end
28
27
 
29
- end
28
+ end
@@ -1,44 +1,39 @@
1
1
  describe "procedure calls" do
2
2
 
3
- let(:empty_args) { VarTuple.new [] }
4
- let(:empty_body) { CmdBlock.empty }
5
-
6
- it "should execute an existing procedure when calling it" do
7
- poner_cmd = Poner.new Verde.new
8
- body = CmdBlock.new [poner_cmd]
9
- my_procedure = Procedure.new 'MyProcedure', empty_args, body
10
- program = Program.new [my_procedure], nil
11
- context = ProgramExecutionContext.for program
3
+ it "evaluates an existing procedure when calling it" do
4
+ poner_cmd = Poner.new verde
5
+ body = CommandBlock.new [poner_cmd]
6
+ my_procedure = Procedure.new 'MyProcedure', no_arguments, body
7
+ program = Program.new [my_procedure], no_return_statement
8
+ context = program_context_for program
12
9
 
13
10
  proc_call = ProcedureCall.new 'MyProcedure', []
14
11
  proc_call.evaluate context
15
12
 
16
- expect(context.head.are_there_balls?(Verde.new)).to be_true
13
+ expect(context.head.are_there_balls?(verde)).to be true
17
14
  end
18
15
 
19
- it "should allow to call a procedure from another procedure" do
20
- poner_cmd = Poner.new Azul.new
21
- inner_procedure_body = CmdBlock.new [poner_cmd]
22
- inner_procedure = Procedure.new 'Inner', empty_args, inner_procedure_body
16
+ it "allows to call a procedure from another procedure" do
17
+ poner_cmd = Poner.new azul
18
+ inner_procedure_body = CommandBlock.new [poner_cmd]
19
+ inner_procedure = Procedure.new 'Inner', no_arguments, inner_procedure_body
23
20
  call_to_inner_procedure = ProcedureCall.new 'Inner', []
24
- outer_procedure_body = CmdBlock.new [call_to_inner_procedure]
25
- outer_procedure = Procedure.new 'Outer', empty_args, outer_procedure_body
26
- program = Program.new [outer_procedure, inner_procedure], nil
27
- program_context = ProgramExecutionContext.for program
21
+ outer_procedure_body = CommandBlock.new [call_to_inner_procedure]
22
+ outer_procedure = Procedure.new 'Outer', no_arguments, outer_procedure_body
23
+ program = Program.new [outer_procedure, inner_procedure], no_return_statement
24
+ program_context = program_context_for program
28
25
 
29
26
  call_to_outer_procedure = ProcedureCall.new 'Outer', []
30
27
  call_to_outer_procedure.evaluate program_context
31
28
 
32
- expect(program_context.head.are_there_balls?(Azul.new)).to be_true
29
+ expect(program_context.head.are_there_balls?(azul)).to be true
33
30
  end
34
31
 
35
- it "should fail to execute an undefined procedure" do
36
- program = Program.new [], nil
37
- context = ProgramExecutionContext.for program
32
+ it "fails to execute an undefined procedure" do
38
33
  proc_call = ProcedureCall.new 'UndefinedProcedure', []
39
34
 
40
- expect { proc_call.evaluate context }
35
+ expect { proc_call.evaluate clean_context }
41
36
  .to raise_error(DefinitionNotFound, DefinitionNotFound.message_for('UndefinedProcedure'))
42
37
  end
43
38
 
44
- end
39
+ end
@@ -1,67 +1,63 @@
1
1
  describe Procedure do
2
2
 
3
- let(:program_context) { ProgramExecutionContext.for Program.new([], nil) }
4
- let(:empty_args) { VarTuple.new [] }
5
- let(:empty_body) { CmdBlock.empty }
6
-
7
- it "should execute its body and leave state in the program context" do
8
- poner_cmd = Poner.new Rojo.new
9
- body = CmdBlock.new [poner_cmd]
10
- procedure = Procedure.new 'MyProcedure', empty_args, body
11
- procedure.evaluate program_context
12
- expect(program_context.head.are_there_balls?(Rojo.new)).to be_true
3
+ let(:context) { clean_context }
4
+
5
+ it "executes its body and leaves state in the program context" do
6
+ poner_cmd = Poner.new rojo
7
+ body = CommandBlock.new [poner_cmd]
8
+ procedure = Procedure.new 'MyProcedure', no_arguments, body
9
+ procedure.evaluate context
10
+ expect(context.head.are_there_balls?(rojo)).to be true
13
11
  end
14
12
 
15
- it "should execute in a new clean context, without having variables defined in another contexts" do
16
- var_name = VarName.new 'var'
17
- program_context.set var_name, Verde.new
13
+ it "fails getting a variable which is in the outer context" do
14
+ var_name = 'var'.to_var_name
15
+ context.set var_name, verde
18
16
 
19
17
  poner_cmd = Poner.new var_name
20
- body = CmdBlock.new [poner_cmd]
21
- procedure = Procedure.new 'MyProcedure', empty_args, body
22
- expect { procedure.evaluate program_context }
23
- .to raise_error(UndefinedVariableError)
18
+ body = CommandBlock.new [poner_cmd]
19
+ procedure = Procedure.new 'MyProcedure', no_arguments, body
20
+ expect { procedure.evaluate context }.to raise_error(UndefinedVariableError)
24
21
  end
25
22
 
26
- it "should set arguments in the new context and they can be used" do
27
- a_color = VarName.new 'a_color'
28
- a_direction = VarName.new 'a_direction'
23
+ it "sets arguments in the new context so they can be used" do
24
+ a_color = 'a_color'.to_var_name
25
+ a_direction = 'a_direction'.to_var_name
29
26
  args = VarTuple.new [a_color, a_direction]
30
27
  mover_cmd = Mover.new a_direction
31
28
  poner_cmd = Poner.new a_color
32
- body = CmdBlock.new [mover_cmd, poner_cmd]
29
+ body = CommandBlock.new [mover_cmd, poner_cmd]
33
30
  procedure = Procedure.new 'MyProc', args, body
34
31
 
35
- procedure.evaluate program_context, [Negro.new, Norte.new]
32
+ procedure.evaluate context, [negro, norte]
36
33
 
37
- expect(program_context.head.are_there_balls?(Negro.new)).to be_true
38
- expect(program_context.head.y_pos).to eq(1)
34
+ expect(context.head.are_there_balls?(negro)).to be true
35
+ expect(context.head.y_pos).to eq(1)
39
36
  end
40
37
 
41
- it "should not set arguments as var names in outer context" do
42
- a_direction = VarName.new 'a_direction'
38
+ it "does not set arguments as var names in outer context" do
39
+ a_direction = 'a_direction'.to_var_name
43
40
  args = VarTuple.new [a_direction]
44
41
  procedure = Procedure.new 'MyProc', args, empty_body
45
42
 
46
- procedure.evaluate program_context, [Oeste.new]
43
+ procedure.evaluate context, [oeste]
47
44
 
48
- expect(program_context.has_variable_named?('a_direction')).to be_false
45
+ expect(context.has_variable_named?('a_direction')).to be false
49
46
  end
50
47
 
51
- it "should fail if it is executed with more arguments than expected" do
52
- procedure = Procedure.new 'MyProcedure', empty_args, empty_body
48
+ it "fails if it is executed with more arguments than expected" do
49
+ procedure = Procedure.new 'MyProcedure', no_arguments, empty_body
53
50
  error_message = "Wrong number of arguments in procedure 'MyProcedure': expected 0, got 1"
54
- expect { procedure.evaluate program_context, [Norte.new] }
51
+ expect { procedure.evaluate context, [norte] }
55
52
  .to raise_error(WrongArgumentsError, error_message)
56
53
  end
57
54
 
58
- it "should fail if it is executed with less arguments than expected" do
59
- arg1, arg2 = VarName.new('arg1'), VarName.new('arg2')
60
- args = VarTuple.new [arg1, arg2]
55
+ it "fails if it is executed with less arguments than expected" do
56
+ args = VarTuple.new ['arg1'.to_var_name, 'arg2'.to_var_name]
61
57
  procedure = Procedure.new 'MyProcedure2', args, empty_body
62
58
  error_message = "Wrong number of arguments in procedure 'MyProcedure2': expected 2, got 1"
63
- expect { procedure.evaluate program_context, [Verde.new] }
59
+ expect { procedure.evaluate context, [verde] }
64
60
  .to raise_error(WrongArgumentsError, error_message)
65
61
  end
66
62
 
67
- end
63
+ end
@@ -1,41 +1,60 @@
1
1
  describe RepeatWithCmd do
2
2
 
3
- let(:context) { ProgramExecutionContext.for double('GobstonesProgram') }
4
- let(:var_name) { VarName.new 'var' }
3
+ let(:context) { clean_context }
4
+ let(:var_name) { 'var'.to_var_name }
5
+
6
+ it "iterates over numbers when evaluating" do
7
+ command_block = CommandBlock.new [Poner.new(rojo)]
8
+ repeat_with = RepeatWithCmd.new var_name, 1.to_gbs_num, 10.to_gbs_num, command_block
5
9
 
6
- it "should iterate over numbers" do
7
- repeat_with = RepeatWithCmd.new var_name, 1.to_gbs_num, 10.to_gbs_num, CmdBlock.new([Poner.new(Rojo.new)])
8
10
  repeat_with.evaluate context
9
- expect(context.head.number_of_balls(Rojo.new)).to eq(10)
11
+
12
+ expect(context.head.number_of_balls(rojo)).to eq(10)
10
13
  end
11
14
 
12
- it "should throw an error if the range values have not the same type" do
13
- repeat_with = RepeatWithCmd.new var_name, 1.to_gbs_num, Este.new, CmdBlock.new([])
15
+ it "raises an error if the range values have not the same type" do
16
+ repeat_with = RepeatWithCmd.new var_name, 1.to_gbs_num, este, empty_body
17
+
14
18
  expect { repeat_with.evaluate context }
15
19
  .to raise_error(GobstonesTypeError, /types don't match in range values/)
16
20
  end
17
21
 
18
- it "should throw an error if the index variable is previously defined" do
19
- repeat_with = RepeatWithCmd.new var_name, 1.to_gbs_num, 5.to_gbs_num, CmdBlock.new([])
22
+ it "raises an error if the index variable is previously defined" do
23
+ repeat_with = RepeatWithCmd.new var_name, 1.to_gbs_num, 5.to_gbs_num, empty_body
24
+
20
25
  context.set var_name, 42.to_gbs_num
26
+
21
27
  expect { repeat_with.evaluate context }
22
28
  .to raise_error(GobstonesRuntimeError, /index variable can't be used because it's already defined/)
23
29
  end
24
30
 
25
- it "should remove the index variable assignment after execution" do
26
- repeat_with = RepeatWithCmd.new var_name, Azul.new, Verde.new, CmdBlock.new([])
31
+ it "removes the index variable assignment after execution" do
32
+ repeat_with = RepeatWithCmd.new var_name, azul, verde, empty_body
33
+
34
+ repeat_with.evaluate context
35
+
36
+ expect(context.has_variable_named?('var')).to be false
37
+ end
38
+
39
+ it "allows to use the index variable inside the command block" do
40
+ cmd_block = CommandBlock.new [Poner.new(var_name)]
41
+ repeat_with = RepeatWithCmd.new var_name, azul, verde, cmd_block
42
+
27
43
  repeat_with.evaluate context
28
- expect(context.has_variable_named?('var')).to be_false
44
+
45
+ expect(context.head.are_there_balls?(azul)).to be true
46
+ expect(context.head.are_there_balls?(negro)).to be true
47
+ expect(context.head.are_there_balls?(rojo)).to be true
48
+ expect(context.head.are_there_balls?(verde)).to be true
29
49
  end
30
50
 
31
- it "should allow to use the index variable inside the command block" do
32
- cmd_block = CmdBlock.new [Poner.new(VarName.new('var'))]
33
- repeat_with = RepeatWithCmd.new var_name, Azul.new, Verde.new, cmd_block
51
+ it "does no iterations if the from is higher than the to" do
52
+ cmd_block = CommandBlock.new [Poner.new(verde)]
53
+ repeat_with = RepeatWithCmd.new var_name, 8.to_gbs_num, 4.to_gbs_num, cmd_block
54
+
34
55
  repeat_with.evaluate context
35
- expect(context.head.are_there_balls?(Azul.new)).to be_true
36
- expect(context.head.are_there_balls?(Negro.new)).to be_true
37
- expect(context.head.are_there_balls?(Rojo.new)).to be_true
38
- expect(context.head.are_there_balls?(Verde.new)).to be_true
56
+
57
+ expect(context.head.are_there_balls?(verde)).to be false
39
58
  end
40
59
 
41
- end
60
+ end
@@ -1,34 +1,35 @@
1
1
  describe Sacar do
2
2
 
3
- let(:context) { ProgramExecutionContext.for double('GobstonesProgram') }
4
- let(:red) { Rojo.new }
3
+ let(:context) { clean_context }
5
4
 
6
- it "should execute" do
7
- 3.times { context.head.put red }
5
+ it "take off balls from the board when evaluating" do
6
+ 3.times { context.head.put rojo }
8
7
 
9
- Sacar.new(red).evaluate context
8
+ Sacar.new(rojo).evaluate context
10
9
 
11
- expect(context.head.number_of_balls(red)).to eq(2)
10
+ expect(context.head.number_of_balls(rojo)).to eq(2)
12
11
  end
13
12
 
14
- it "should undo" do
15
- Sacar.new(red).undo context
13
+ it "undoes a command" do
14
+ Sacar.new(rojo).undo context
16
15
 
17
- expect(context.head.number_of_balls(red)).to eq(1)
16
+ expect(context.head.number_of_balls(rojo)).to eq(1)
18
17
  end
19
18
 
20
- it "should return the opposite cmd" do
21
- expect(Sacar.new(red).opposite).to eq(Poner.new(red))
19
+ it "returns the opposite command" do
20
+ opposite_command = Sacar.new(rojo).opposite
21
+
22
+ expect(opposite_command).to eq(Poner.new(rojo))
22
23
  end
23
24
 
24
- it "should fail if there are no balls in the board" do
25
- expect { Sacar.new(red).evaluate(context) }.
25
+ it "fails if there are no balls in the board" do
26
+ expect { Sacar.new(rojo).evaluate(context) }.
26
27
  to raise_error(EmptyCellError)
27
28
  end
28
29
 
29
- it "should fail if types don't match" do
30
- expect { Sacar.new(True.new).evaluate(context) }.
30
+ it "fails if the argument is not a color" do
31
+ expect { Sacar.new(true_value).evaluate(context) }.
31
32
  to raise_error(GobstonesTypeError, /is not a color/)
32
33
  end
33
34
 
34
- end
35
+ end
@@ -0,0 +1,13 @@
1
+ describe SingleAssignment do
2
+
3
+ let(:context) { clean_context }
4
+ let(:a) { 'a'.to_var_name }
5
+
6
+ it "evaluates the associated expression to the var name" do
7
+ assign = SingleAssignment.new a, Add.new(3.to_gbs_num, 4.to_gbs_num)
8
+ assign.evaluate context
9
+ expect(context.has_variable_named?('a')).to be true
10
+ expect(context.get(a)).to eq(7.to_gbs_num)
11
+ end
12
+
13
+ end
@@ -1,6 +1,6 @@
1
1
  describe Skip do
2
2
 
3
- let(:context) { ProgramExecutionContext.for Program.new([], nil) }
3
+ let(:context) { clean_context }
4
4
 
5
5
  it "evaluates and does nothing" do
6
6
  Skip.new.evaluate context
@@ -9,4 +9,4 @@ describe Skip do
9
9
  expect(context.head.board).to be_empty
10
10
  end
11
11
 
12
- end
12
+ end