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
@@ -14,4 +14,4 @@ module Gobstones
14
14
 
15
15
  end
16
16
 
17
- end
17
+ end
@@ -2,5 +2,4 @@ require 'gobstones/runner/board'
2
2
  require 'gobstones/runner/cell'
3
3
  require 'gobstones/runner/execution_context'
4
4
  require 'gobstones/runner/head'
5
-
6
- require 'gobstones/runner/errors/all'
5
+ require 'gobstones/runner/errors/all'
@@ -8,10 +8,14 @@ module Gobstones
8
8
 
9
9
  attr_reader :rows, :columns
10
10
 
11
- def initialize(r, c)
11
+ def initialize(r, c, matrix=[])
12
12
  @rows, @columns = r, c
13
- @matrix = []
14
- r.times { @matrix << []; c.times { @matrix.last << Cell.new } }
13
+ if matrix.empty?
14
+ @matrix = []
15
+ r.times { @matrix << []; c.times { @matrix.last << Cell.new } }
16
+ else
17
+ @matrix = matrix
18
+ end
15
19
  end
16
20
 
17
21
  def cell_at(x, y)
@@ -50,8 +54,13 @@ module Gobstones
50
54
  true
51
55
  end
52
56
 
57
+ def clone
58
+ new_matrix = @matrix.map { |row| row.map { |cell| cell.clone } }
59
+ self.class.new @rows, @columns, new_matrix
60
+ end
61
+
53
62
  end
54
63
 
55
64
  end
56
65
 
57
- end
66
+ end
@@ -37,6 +37,16 @@ module Gobstones
37
37
  @values.values.all? { |value| value.zero? }
38
38
  end
39
39
 
40
+ def clone
41
+ self.class.new.tap do |copy|
42
+ [Azul.new, Negro.new, Rojo.new, Verde.new].each do |color|
43
+ number_of_balls(color).times do
44
+ copy.put color
45
+ end
46
+ end
47
+ end
48
+ end
49
+
40
50
  private
41
51
 
42
52
  def check(color)
@@ -5,4 +5,4 @@ require 'gobstones/runner/errors/gobstones_runtime_error'
5
5
  require 'gobstones/runner/errors/gobstones_type_error'
6
6
  require 'gobstones/runner/errors/undefined_variable_error'
7
7
  require 'gobstones/runner/errors/out_of_board_error'
8
- require 'gobstones/runner/errors/wrong_arguments_error'
8
+ require 'gobstones/runner/errors/wrong_arguments_error'
@@ -16,4 +16,4 @@ module Gobstones
16
16
 
17
17
  end
18
18
 
19
- end
19
+ end
@@ -10,20 +10,30 @@ module Gobstones
10
10
  @values = {}
11
11
  end
12
12
 
13
- def set(var_name, value)
14
- @values[var_name] = value
13
+ def set(variable_name, value)
14
+ @values[variable_name] = value
15
15
  end
16
16
 
17
- def get(var_name)
18
- @values[var_name] || (raise UndefinedVariableError)
17
+ def get(variable_name)
18
+ @values[variable_name] || undefined_variable_error
19
19
  end
20
20
 
21
- def clear(var_name)
22
- @values.delete(var_name)
21
+ def clear(variable_name)
22
+ @values.delete(variable_name)
23
23
  end
24
24
 
25
25
  def has_variable_named?(name)
26
- @values.keys.any? { |var| var.name == name }
26
+ @values.keys.any? { |variable| variable.named? name }
27
+ end
28
+
29
+ def program_context
30
+ raise 'subclass responsibility'
31
+ end
32
+
33
+ protected
34
+
35
+ def undefined_variable_error
36
+ raise UndefinedVariableError
27
37
  end
28
38
 
29
39
  end
@@ -43,14 +53,10 @@ module Gobstones
43
53
  end
44
54
 
45
55
  def definition_named(name, found_block, not_found_block)
46
- found_definition = @program.definitions.find { |definition|
47
- definition.named? name
48
- }
49
- if found_definition
50
- found_block.call found_definition
51
- else
52
- not_found_block.call
53
- end
56
+ if_none = proc { return not_found_block.call }
57
+ found_definition = @program.definitions.detect(if_none) \
58
+ { |definition| definition.named? name }
59
+ found_block.call found_definition
54
60
  end
55
61
 
56
62
  def program_context
@@ -66,7 +72,7 @@ module Gobstones
66
72
  class ProcedureExecutionContext < ExecutionContext
67
73
 
68
74
  def self.based_on(outer_context)
69
- self.new outer_context
75
+ new outer_context
70
76
  end
71
77
 
72
78
  def initialize(outer_context)
@@ -84,6 +90,50 @@ module Gobstones
84
90
 
85
91
  end
86
92
 
93
+ class FunctionExecutionContext < ExecutionContext
94
+
95
+ attr_reader :head
96
+
97
+ def self.based_on(outer_context)
98
+ new outer_context
99
+ end
100
+
101
+ def initialize(outer_context)
102
+ super()
103
+ @outer_context = outer_context
104
+ @head = outer_context.head.clone
105
+ end
106
+
107
+ def program_context
108
+ @outer_context.program_context
109
+ end
110
+
111
+ end
112
+
113
+ class NullExecutionContext < ExecutionContext
114
+
115
+ def set(variable_name, value)
116
+
117
+ end
118
+
119
+ def get(variable_name)
120
+ undefined_variable_error
121
+ end
122
+
123
+ def clear(variable_name)
124
+
125
+ end
126
+
127
+ def has_variable_named?(variable_name)
128
+ false
129
+ end
130
+
131
+ def program_context
132
+ raise 'a null execution does not know its program context'
133
+ end
134
+
135
+ end
136
+
87
137
  end
88
138
 
89
139
  end
@@ -15,9 +15,12 @@ module Gobstones
15
15
  new.at_random
16
16
  end
17
17
 
18
+ def self.with_position_and_board(x_pos, y_pos, board)
19
+ new.with_position_and_board x_pos, y_pos, board
20
+ end
21
+
18
22
  def initialize
19
- go_to_origin
20
- @board = Board.new MAX_ROWS, MAX_COLS
23
+ with_position_and_board 0, 0, Board.new(MAX_ROWS, MAX_COLS)
21
24
  end
22
25
 
23
26
  def at_random
@@ -25,6 +28,13 @@ module Gobstones
25
28
  self
26
29
  end
27
30
 
31
+ def with_position_and_board(x_pos, y_pos, board)
32
+ @x_pos = x_pos
33
+ @y_pos = y_pos
34
+ @board = board
35
+ self
36
+ end
37
+
28
38
  def can_move?(dir)
29
39
  check dir
30
40
  dir.can_move? self
@@ -87,6 +97,10 @@ module Gobstones
87
97
  @board.are_there_balls? x_pos, y_pos, color
88
98
  end
89
99
 
100
+ def clone
101
+ self.class.with_position_and_board x_pos, y_pos, board.clone
102
+ end
103
+
90
104
  private
91
105
 
92
106
  def check(dir)
@@ -98,4 +112,4 @@ module Gobstones
98
112
 
99
113
  end
100
114
 
101
- end
115
+ end
@@ -0,0 +1,75 @@
1
+ module GobstonesLangTestObjects
2
+
3
+ # Programs, contexts and definitions
4
+
5
+ def clean_context
6
+ program_context_for empty_program
7
+ end
8
+
9
+ def program_context_for(program)
10
+ ProgramExecutionContext.for program
11
+ end
12
+
13
+ def empty_program
14
+ Program.new no_definitions, no_return_statement
15
+ end
16
+
17
+ def no_definitions
18
+ []
19
+ end
20
+
21
+ def no_arguments
22
+ VarTuple.empty
23
+ end
24
+
25
+ def no_return_statement
26
+ NoReturnStatement.new
27
+ end
28
+
29
+ def empty_body
30
+ CommandBlock.empty
31
+ end
32
+
33
+ # Literals
34
+
35
+ def true_value
36
+ True.new
37
+ end
38
+
39
+ def false_value
40
+ False.new
41
+ end
42
+
43
+ def verde
44
+ Verde.new
45
+ end
46
+
47
+ def azul
48
+ Azul.new
49
+ end
50
+
51
+ def negro
52
+ Negro.new
53
+ end
54
+
55
+ def rojo
56
+ Rojo.new
57
+ end
58
+
59
+ def norte
60
+ Norte.new
61
+ end
62
+
63
+ def sur
64
+ Sur.new
65
+ end
66
+
67
+ def este
68
+ Este.new
69
+ end
70
+
71
+ def oeste
72
+ Oeste.new
73
+ end
74
+
75
+ end
@@ -1,8 +1,8 @@
1
1
  describe Boom do
2
2
 
3
- it "should raise an exception when evaluating, with the right message" do
3
+ it "raises an error when evaluating, with the message specified" do
4
4
  msg = 'This is a program error'
5
- expect { Boom.new(msg).evaluate }.to raise_error(BoomError, msg)
5
+ expect { Boom.new(msg).evaluate(clean_context) }.to raise_error(BoomError, msg)
6
6
  end
7
7
 
8
- end
8
+ end
@@ -1,21 +1,21 @@
1
- describe CmdBlock do
1
+ describe CommandBlock do
2
2
 
3
- it "should evaluate all inner commands" do
4
- program = Program.new [], nil
5
- context = ProgramExecutionContext.for program
6
- cmd_block = CmdBlock.new [
7
- Poner.new(Rojo.new), Poner.new(Verde.new),
8
- Poner.new(Negro.new), Poner.new(Azul.new)]
3
+ let(:context) { clean_context }
4
+
5
+ it "evaluates all inner commands" do
6
+ cmd_block = CommandBlock.new [
7
+ Poner.new(rojo), Poner.new(verde),
8
+ Poner.new(negro), Poner.new(azul)]
9
9
  cmd_block.evaluate context
10
- expect(context.head.are_there_balls?(Rojo.new)).to be_true
11
- expect(context.head.are_there_balls?(Azul.new)).to be_true
12
- expect(context.head.are_there_balls?(Negro.new)).to be_true
13
- expect(context.head.are_there_balls?(Verde.new)).to be_true
10
+ expect(context.head.are_there_balls?(azul)).to be true
11
+ expect(context.head.are_there_balls?(negro)).to be true
12
+ expect(context.head.are_there_balls?(rojo)).to be true
13
+ expect(context.head.are_there_balls?(verde)).to be true
14
14
  end
15
15
 
16
16
  it "builds an empty command block" do
17
- expect(CmdBlock.new []).to be_empty
18
- expect(CmdBlock.empty).to be_empty
17
+ expect(CommandBlock.new []).to be_empty
18
+ expect(CommandBlock.empty).to be_empty
19
19
  end
20
20
 
21
- end
21
+ end
@@ -1,49 +1,50 @@
1
1
  describe "if command" do
2
2
 
3
- let(:context) { ProgramExecutionContext.for double('GobstonesProgram') }
4
- let(:then_block) { CmdBlock.new [Poner.new(Verde.new)] }
5
- let(:else_block) { CmdBlock.new [Poner.new(Rojo.new)] }
3
+ let(:context) { clean_context }
4
+ let(:then_block) { CommandBlock.new [Poner.new(verde)] }
5
+ let(:else_block) { CommandBlock.new [Poner.new(rojo)] }
6
6
 
7
7
  describe "if-then" do
8
8
 
9
- it "should evaluate the block if the condition is true" do
10
- if_cmd = IfCmd.new True.new, then_block
9
+ it "evaluates the 'then' command block if the condition is true" do
10
+ if_cmd = IfCmd.new true_value, then_block
11
11
  if_cmd.evaluate context
12
- expect(context.head.are_there_balls?(Verde.new)).to be_true
12
+ expect(context.head.are_there_balls?(verde)).to be true
13
13
  end
14
14
 
15
- it "should not evaluate the block if the condition is false" do
16
- if_cmd = IfCmd.new False.new, then_block
15
+ it "does not evaluate the 'then' command block if the condition is false" do
16
+ if_cmd = IfCmd.new false_value, then_block
17
17
  if_cmd.evaluate context
18
- expect(context.head.are_there_balls?(Verde.new)).to be_false
18
+ expect(context.head.are_there_balls?(verde)).to be false
19
19
  end
20
20
 
21
- it "should raise a type error if the condition is not boolean" do
22
- [Number.new(42), Norte.new, Verde.new].each do |value|
21
+ it "raises a type error if the condition is not boolean" do
22
+ [42.to_gbs_num, norte, verde].each do |value|
23
23
  if_cmd = IfCmd.new value, then_block
24
24
  expect { if_cmd.evaluate context }
25
25
  .to raise_error(GobstonesTypeError, /is not a boolean/)
26
26
  end
27
+
27
28
  end
28
29
 
29
30
  end
30
31
 
31
32
  describe "if-then-else" do
32
33
 
33
- it "should evaluate the 'then' block and not evaluate the 'else' block" do
34
- if_cmd = IfElseCmd.new True.new, then_block, else_block
34
+ it "evaluates the 'then' block and it does not evaluate the 'else' block" do
35
+ if_cmd = IfElseCmd.new true_value, then_block, else_block
35
36
  if_cmd.evaluate context
36
- expect(context.head.are_there_balls?(Verde.new)).to be_true
37
- expect(context.head.are_there_balls?(Rojo.new)).to be_false
37
+ expect(context.head.are_there_balls?(verde)).to be true
38
+ expect(context.head.are_there_balls?(rojo)).to be false
38
39
  end
39
40
 
40
- it "should not evaluate the 'then' block and evaluate the 'else' block" do
41
- if_cmd = IfElseCmd.new False.new, then_block, else_block
41
+ it "does not evaluate the 'then' block and it evaluates the 'else' block" do
42
+ if_cmd = IfElseCmd.new false_value, then_block, else_block
42
43
  if_cmd.evaluate context
43
- expect(context.head.are_there_balls?(Verde.new)).to be_false
44
- expect(context.head.are_there_balls?(Rojo.new)).to be_true
44
+ expect(context.head.are_there_balls?(verde)).to be false
45
+ expect(context.head.are_there_balls?(rojo)).to be true
45
46
  end
46
47
 
47
48
  end
48
49
 
49
- end
50
+ end
@@ -1,8 +1,8 @@
1
1
  describe IrAlOrigen do
2
2
 
3
- let(:context) { ProgramExecutionContext.for double('GobstonesProgram') }
3
+ let(:context) { clean_context }
4
4
 
5
- it "should evaluate and put the head in 0, 0" do
5
+ it "puts the head in 0, 0 when evaluating" do
6
6
  context.head.move_north
7
7
  context.head.move_east
8
8
  ir_al_origen = IrAlOrigen.new
@@ -13,4 +13,4 @@ describe IrAlOrigen do
13
13
  expect(context.head.y_pos).to eq(0)
14
14
  end
15
15
 
16
- end
16
+ end