gobstones 0.0.1.1

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 (135) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.rspec +3 -0
  4. data/.ruby-version +1 -0
  5. data/.simplecov +3 -0
  6. data/.travis.yml +4 -0
  7. data/CHANGELOG +4 -0
  8. data/Gemfile +12 -0
  9. data/Gemfile.lock +47 -0
  10. data/LICENSE +675 -0
  11. data/README.md +17 -0
  12. data/Rakefile +4 -0
  13. data/bin/gobstones +12 -0
  14. data/gobstones.gemspec +24 -0
  15. data/lib/gobstones/cli/board_template +39 -0
  16. data/lib/gobstones/cli/printer.rb +106 -0
  17. data/lib/gobstones/cli/runner.rb +52 -0
  18. data/lib/gobstones/extensions/all.rb +2 -0
  19. data/lib/gobstones/extensions/boolean.rb +17 -0
  20. data/lib/gobstones/extensions/fixnum.rb +9 -0
  21. data/lib/gobstones/lang/all.rb +5 -0
  22. data/lib/gobstones/lang/commands/all.rb +13 -0
  23. data/lib/gobstones/lang/commands/assignments.rb +29 -0
  24. data/lib/gobstones/lang/commands/boom_cmd.rb +28 -0
  25. data/lib/gobstones/lang/commands/command_block.rb +37 -0
  26. data/lib/gobstones/lang/commands/conditional_cmd.rb +27 -0
  27. data/lib/gobstones/lang/commands/if_cmd.rb +38 -0
  28. data/lib/gobstones/lang/commands/ir_al_origen_cmd.rb +19 -0
  29. data/lib/gobstones/lang/commands/mover_cmd.rb +25 -0
  30. data/lib/gobstones/lang/commands/poner_cmd.rb +31 -0
  31. data/lib/gobstones/lang/commands/procedure_call.rb +23 -0
  32. data/lib/gobstones/lang/commands/repeat_with_cmd.rb +73 -0
  33. data/lib/gobstones/lang/commands/sacar_cmd.rb +31 -0
  34. data/lib/gobstones/lang/commands/skip_cmd.rb +19 -0
  35. data/lib/gobstones/lang/commands/vaciar_tablero_cmd.rb +19 -0
  36. data/lib/gobstones/lang/commands/while_cmd.rb +25 -0
  37. data/lib/gobstones/lang/definitions/all.rb +4 -0
  38. data/lib/gobstones/lang/definitions/definition.rb +32 -0
  39. data/lib/gobstones/lang/definitions/definition_call.rb +24 -0
  40. data/lib/gobstones/lang/definitions/function.rb +14 -0
  41. data/lib/gobstones/lang/definitions/main.rb +26 -0
  42. data/lib/gobstones/lang/definitions/no_return_statement.rb +15 -0
  43. data/lib/gobstones/lang/definitions/procedure.rb +44 -0
  44. data/lib/gobstones/lang/definitions/return_from_function.rb +22 -0
  45. data/lib/gobstones/lang/definitions/return_from_main.rb +22 -0
  46. data/lib/gobstones/lang/definitions/var_tuple.rb +26 -0
  47. data/lib/gobstones/lang/expressions/all.rb +8 -0
  48. data/lib/gobstones/lang/expressions/arithmetic_expressions.rb +52 -0
  49. data/lib/gobstones/lang/expressions/boolean_expressions.rb +29 -0
  50. data/lib/gobstones/lang/expressions/comparison_expressions.rb +45 -0
  51. data/lib/gobstones/lang/expressions/function_call.rb +15 -0
  52. data/lib/gobstones/lang/expressions/one_arg_expression.rb +21 -0
  53. data/lib/gobstones/lang/expressions/parentheses_expression.rb +13 -0
  54. data/lib/gobstones/lang/expressions/primitive_functions.rb +68 -0
  55. data/lib/gobstones/lang/expressions/two_arg_expression.rb +34 -0
  56. data/lib/gobstones/lang/expressions/type_bound_functions.rb +66 -0
  57. data/lib/gobstones/lang/expressions/var_name.rb +31 -0
  58. data/lib/gobstones/lang/literals/all.rb +4 -0
  59. data/lib/gobstones/lang/literals/booleans.rb +109 -0
  60. data/lib/gobstones/lang/literals/colors.rb +94 -0
  61. data/lib/gobstones/lang/literals/directions.rb +137 -0
  62. data/lib/gobstones/lang/literals/literal.rb +63 -0
  63. data/lib/gobstones/lang/literals/number.rb +49 -0
  64. data/lib/gobstones/lang/program.rb +32 -0
  65. data/lib/gobstones/modules/equal_by_class.rb +13 -0
  66. data/lib/gobstones/parser/ast/ast.rb +210 -0
  67. data/lib/gobstones/parser/grammar/gobstones.treetop +316 -0
  68. data/lib/gobstones/parser/parse_error.rb +17 -0
  69. data/lib/gobstones/parser/treetop_parser.rb +73 -0
  70. data/lib/gobstones/runner/all.rb +6 -0
  71. data/lib/gobstones/runner/board.rb +57 -0
  72. data/lib/gobstones/runner/cell.rb +60 -0
  73. data/lib/gobstones/runner/errors/all.rb +8 -0
  74. data/lib/gobstones/runner/errors/boom_error.rb +11 -0
  75. data/lib/gobstones/runner/errors/definition_not_found_error.rb +19 -0
  76. data/lib/gobstones/runner/errors/empty_cell_error.rb +11 -0
  77. data/lib/gobstones/runner/errors/gobstones_runtime_error.rb +11 -0
  78. data/lib/gobstones/runner/errors/gobstones_type_error.rb +11 -0
  79. data/lib/gobstones/runner/errors/out_of_board_error.rb +11 -0
  80. data/lib/gobstones/runner/errors/undefined_variable_error.rb +11 -0
  81. data/lib/gobstones/runner/errors/wrong_arguments_error.rb +11 -0
  82. data/lib/gobstones/runner/execution_context.rb +89 -0
  83. data/lib/gobstones/runner/head.rb +101 -0
  84. data/lib/gobstones/type_check_result.rb +16 -0
  85. data/spec/lang/commands/assignments_spec.rb +13 -0
  86. data/spec/lang/commands/boom_cmd_spec.rb +8 -0
  87. data/spec/lang/commands/cmd_block_spec.rb +21 -0
  88. data/spec/lang/commands/if_cmd_spec.rb +49 -0
  89. data/spec/lang/commands/ir_al_origen_cmd_spec.rb +16 -0
  90. data/spec/lang/commands/mover_cmd_spec.rb +38 -0
  91. data/spec/lang/commands/poner_cmd_spec.rb +29 -0
  92. data/spec/lang/commands/procedure_call_spec.rb +44 -0
  93. data/spec/lang/commands/procedure_spec.rb +67 -0
  94. data/spec/lang/commands/repeat_with_cmd_spec.rb +41 -0
  95. data/spec/lang/commands/sacar_cmd_spec.rb +34 -0
  96. data/spec/lang/commands/skip_cmd_spec.rb +12 -0
  97. data/spec/lang/commands/vaciar_tablero_cmd_spec.rb +13 -0
  98. data/spec/lang/commands/while_cmd_spec.rb +37 -0
  99. data/spec/lang/expressions/arithmetic_expressions_spec.rb +108 -0
  100. data/spec/lang/expressions/boolean_expressions_spec.rb +56 -0
  101. data/spec/lang/expressions/comparison_expressions_spec.rb +285 -0
  102. data/spec/lang/expressions/primitive_functions_spec.rb +126 -0
  103. data/spec/lang/expressions/type_bound_functions_spec.rb +39 -0
  104. data/spec/lang/expressions/var_name_spec.rb +16 -0
  105. data/spec/lang/literals/booleans_spec.rb +13 -0
  106. data/spec/lang/literals/colors_spec.rb +13 -0
  107. data/spec/lang/literals/directions_spec.rb +45 -0
  108. data/spec/lang/literals/numbers_spec.rb +8 -0
  109. data/spec/matchers/parse_matcher.rb +84 -0
  110. data/spec/parser/arithmetic_expressions_spec.rb +129 -0
  111. data/spec/parser/assignments_spec.rb +39 -0
  112. data/spec/parser/boolean_expressions_spec.rb +111 -0
  113. data/spec/parser/command_block_spec.rb +50 -0
  114. data/spec/parser/data_types_spec.rb +67 -0
  115. data/spec/parser/function_calls_spec.rb +37 -0
  116. data/spec/parser/function_definitions_spec.rb +50 -0
  117. data/spec/parser/gobstones_program_spec.rb +55 -0
  118. data/spec/parser/if_command_spec.rb +46 -0
  119. data/spec/parser/main_definition_spec.rb +42 -0
  120. data/spec/parser/nested_expressions_spec.rb +39 -0
  121. data/spec/parser/primitive_expressions_spec.rb +105 -0
  122. data/spec/parser/procedure_calls_spec.rb +36 -0
  123. data/spec/parser/procedure_definitions_spec.rb +39 -0
  124. data/spec/parser/repeat_with_command_spec.rb +23 -0
  125. data/spec/parser/simple_commands_spec.rb +62 -0
  126. data/spec/parser/treetop_parser_spec.rb +109 -0
  127. data/spec/parser/var_tuple_spec.rb +30 -0
  128. data/spec/parser/while_command_spec.rb +30 -0
  129. data/spec/runner/board_spec.rb +85 -0
  130. data/spec/runner/cell_spec.rb +72 -0
  131. data/spec/runner/execution_context_spec.rb +64 -0
  132. data/spec/runner/head_spec.rb +139 -0
  133. data/spec/spec_helper.rb +15 -0
  134. data/spec/type_checker_spec.rb +37 -0
  135. metadata +242 -0
@@ -0,0 +1,17 @@
1
+ module Gobstones
2
+
3
+ module Parser
4
+
5
+ class ParseError < StandardError
6
+
7
+ attr_reader :parser, :code
8
+
9
+ def initialize(parser, code)
10
+ @parser, @code = parser, code
11
+ end
12
+
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,73 @@
1
+ require 'treetop'
2
+ require 'gobstones/parser/ast/ast'
3
+ require 'gobstones/parser/parse_error'
4
+
5
+ module Gobstones
6
+
7
+ module Parser
8
+
9
+ class TreetopParser
10
+
11
+ def initialize
12
+ Treetop.load grammar_file
13
+ @parser = GobstonesParser.new
14
+ end
15
+
16
+ def parse(code)
17
+ code_without_comments = remove_comments_from(code)
18
+ result = @parser.parse code_without_comments
19
+ raise ParseError.new(self, code_without_comments) if result.nil?
20
+ result.value
21
+ end
22
+
23
+ def failure_reason
24
+ @parser.failure_reason
25
+ end
26
+
27
+ def failure_line
28
+ @parser.failure_line
29
+ end
30
+
31
+ def failure_column
32
+ @parser.failure_column
33
+ end
34
+
35
+ def remove_comments_from(code)
36
+ code
37
+ .gsub(single_line_c_style_comments_regex, '')
38
+ .gsub(single_line_haskell_style_comments_regex, '')
39
+ .gsub(multi_line_c_style_comments_regex, '')
40
+ .gsub(multi_line_haskell_style_comments_regex, '')
41
+ end
42
+
43
+ private
44
+
45
+ def grammar_file
46
+ File.join base_path, 'grammar/gobstones'
47
+ end
48
+
49
+ def base_path
50
+ File.expand_path File.dirname(__FILE__)
51
+ end
52
+
53
+ def single_line_c_style_comments_regex
54
+ /\/\/.*$/
55
+ end
56
+
57
+ def single_line_haskell_style_comments_regex
58
+ /--.*$/
59
+ end
60
+
61
+ def multi_line_c_style_comments_regex
62
+ /\/\*.*?\*\//m
63
+ end
64
+
65
+ def multi_line_haskell_style_comments_regex
66
+ /{-.*?\-}/m
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,6 @@
1
+ require 'gobstones/runner/board'
2
+ require 'gobstones/runner/cell'
3
+ require 'gobstones/runner/execution_context'
4
+ require 'gobstones/runner/head'
5
+
6
+ require 'gobstones/runner/errors/all'
@@ -0,0 +1,57 @@
1
+ require 'gobstones/runner/cell'
2
+
3
+ module Gobstones
4
+
5
+ module Runner
6
+
7
+ class Board
8
+
9
+ attr_reader :rows, :columns
10
+
11
+ def initialize(r, c)
12
+ @rows, @columns = r, c
13
+ @matrix = []
14
+ r.times { @matrix << []; c.times { @matrix.last << Cell.new } }
15
+ end
16
+
17
+ def cell_at(x, y)
18
+ raise OutOfBoardError unless \
19
+ x.between?(0, rows - 1) && y.between?(0, columns - 1)
20
+
21
+ @matrix[x][y]
22
+ end
23
+
24
+ def each_cell
25
+ @matrix.each { |row| row.each { |cell| yield cell } }
26
+ end
27
+
28
+ def put(x, y, color)
29
+ cell_at(x, y).put(color)
30
+ end
31
+
32
+ def take_out(x, y, color)
33
+ cell_at(x, y).take_out(color)
34
+ end
35
+
36
+ def are_there_balls?(x, y, color)
37
+ cell_at(x, y).are_there_balls?(color)
38
+ end
39
+
40
+ def number_of_balls(x, y, color)
41
+ cell_at(x, y).number_of_balls(color)
42
+ end
43
+
44
+ def empty!
45
+ each_cell { |cell| cell.empty! }
46
+ end
47
+
48
+ def empty?
49
+ each_cell { |cell| return false unless cell.empty? }
50
+ true
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,60 @@
1
+ module Gobstones
2
+
3
+ module Runner
4
+
5
+ class Cell
6
+
7
+ def initialize
8
+ @values = { Azul => 0, Negro => 0, Rojo => 0, Verde => 0 }
9
+ end
10
+
11
+ def put(color)
12
+ check color
13
+ lookup(color) { |value| value + 1 }
14
+ end
15
+
16
+ def take_out(color)
17
+ check color
18
+ raise EmptyCellError unless are_there_balls?(color)
19
+ lookup(color) { |value| value - 1 }
20
+ end
21
+
22
+ def are_there_balls?(color)
23
+ check color
24
+ number_of_balls(color) > 0
25
+ end
26
+
27
+ def number_of_balls(color)
28
+ check color
29
+ lookup color
30
+ end
31
+
32
+ def empty!
33
+ initialize
34
+ end
35
+
36
+ def empty?
37
+ @values.values.all? { |value| value.zero? }
38
+ end
39
+
40
+ private
41
+
42
+ def check(color)
43
+ raise "'#{color}' is not a color" \
44
+ unless [Azul, Negro, Rojo, Verde].include? color.class
45
+ end
46
+
47
+ def lookup(color)
48
+ value = @values.keys.detect { |col| col == color.class }
49
+ if block_given?
50
+ @values[value] = yield @values[value]
51
+ else
52
+ @values[value]
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,8 @@
1
+ require 'gobstones/runner/errors/boom_error'
2
+ require 'gobstones/runner/errors/definition_not_found_error'
3
+ require 'gobstones/runner/errors/empty_cell_error'
4
+ require 'gobstones/runner/errors/gobstones_runtime_error'
5
+ require 'gobstones/runner/errors/gobstones_type_error'
6
+ require 'gobstones/runner/errors/undefined_variable_error'
7
+ require 'gobstones/runner/errors/out_of_board_error'
8
+ require 'gobstones/runner/errors/wrong_arguments_error'
@@ -0,0 +1,11 @@
1
+ module Gobstones
2
+
3
+ module Runner
4
+
5
+ class BoomError < StandardError
6
+
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,19 @@
1
+ module Gobstones
2
+
3
+ module Runner
4
+
5
+ class DefinitionNotFound < StandardError
6
+
7
+ def self.new(definition_name)
8
+ super(message_for(definition_name))
9
+ end
10
+
11
+ def self.message_for(definition_name)
12
+ "definition named '#{definition_name}' not found in program"
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,11 @@
1
+ module Gobstones
2
+
3
+ module Runner
4
+
5
+ class EmptyCellError < StandardError
6
+
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,11 @@
1
+ module Gobstones
2
+
3
+ module Runner
4
+
5
+ class GobstonesRuntimeError < StandardError
6
+
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,11 @@
1
+ module Gobstones
2
+
3
+ module Runner
4
+
5
+ class GobstonesTypeError < StandardError
6
+
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,11 @@
1
+ module Gobstones
2
+
3
+ module Runner
4
+
5
+ class OutOfBoardError < StandardError
6
+
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,11 @@
1
+ module Gobstones
2
+
3
+ module Runner
4
+
5
+ class UndefinedVariableError < StandardError
6
+
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,11 @@
1
+ module Gobstones
2
+
3
+ module Runner
4
+
5
+ class WrongArgumentsError < StandardError
6
+
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,89 @@
1
+ require 'gobstones/runner/head'
2
+
3
+ module Gobstones
4
+
5
+ module Runner
6
+
7
+ class ExecutionContext
8
+
9
+ def initialize
10
+ @values = {}
11
+ end
12
+
13
+ def set(var_name, value)
14
+ @values[var_name] = value
15
+ end
16
+
17
+ def get(var_name)
18
+ @values[var_name] || (raise UndefinedVariableError)
19
+ end
20
+
21
+ def clear(var_name)
22
+ @values.delete(var_name)
23
+ end
24
+
25
+ def has_variable_named?(name)
26
+ @values.keys.any? { |var| var.name == name }
27
+ end
28
+
29
+ end
30
+
31
+ class ProgramExecutionContext < ExecutionContext
32
+
33
+ attr_reader :head
34
+
35
+ def self.for(program)
36
+ self.new program
37
+ end
38
+
39
+ def initialize(program)
40
+ super()
41
+ @head = Head.new
42
+ @program = program
43
+ end
44
+
45
+ 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
54
+ end
55
+
56
+ def program_context
57
+ self
58
+ end
59
+
60
+ def board
61
+ head.board
62
+ end
63
+
64
+ end
65
+
66
+ class ProcedureExecutionContext < ExecutionContext
67
+
68
+ def self.based_on(outer_context)
69
+ self.new outer_context
70
+ end
71
+
72
+ def initialize(outer_context)
73
+ super()
74
+ @outer_context = outer_context
75
+ end
76
+
77
+ def head
78
+ @outer_context.head
79
+ end
80
+
81
+ def program_context
82
+ @outer_context.program_context
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+
89
+ end
@@ -0,0 +1,101 @@
1
+ require 'gobstones/runner/board'
2
+
3
+ module Gobstones
4
+
5
+ module Runner
6
+
7
+ class Head
8
+
9
+ MAX_ROWS = 9
10
+ MAX_COLS = 9
11
+
12
+ attr_reader :board, :x_pos, :y_pos
13
+
14
+ def self.at_random
15
+ new.at_random
16
+ end
17
+
18
+ def initialize
19
+ go_to_origin
20
+ @board = Board.new MAX_ROWS, MAX_COLS
21
+ end
22
+
23
+ def at_random
24
+ @x_pos, @y_pos = rand(MAX_ROWS), rand(MAX_COLS)
25
+ self
26
+ end
27
+
28
+ def can_move?(dir)
29
+ check dir
30
+ dir.can_move? self
31
+ end
32
+
33
+ def can_move_north?
34
+ @y_pos < MAX_COLS-1
35
+ end
36
+
37
+ def can_move_south?
38
+ @y_pos > 0
39
+ end
40
+
41
+ def can_move_east?
42
+ @x_pos < MAX_ROWS-1
43
+ end
44
+
45
+ def can_move_west?
46
+ @x_pos > 0
47
+ end
48
+
49
+ def move(dir)
50
+ raise OutOfBoardError unless can_move?(dir)
51
+ dir.move self
52
+ end
53
+
54
+ def move_north
55
+ @y_pos += 1
56
+ end
57
+
58
+ def move_south
59
+ @y_pos -= 1
60
+ end
61
+
62
+ def move_east
63
+ @x_pos += 1
64
+ end
65
+
66
+ def move_west
67
+ @x_pos -= 1
68
+ end
69
+
70
+ def go_to_origin
71
+ @x_pos, @y_pos = 0, 0
72
+ end
73
+
74
+ def put(color)
75
+ @board.put x_pos, y_pos, color
76
+ end
77
+
78
+ def take_out(color)
79
+ @board.take_out x_pos, y_pos, color
80
+ end
81
+
82
+ def number_of_balls(color)
83
+ @board.number_of_balls x_pos, y_pos, color
84
+ end
85
+
86
+ def are_there_balls?(color)
87
+ @board.are_there_balls? x_pos, y_pos, color
88
+ end
89
+
90
+ private
91
+
92
+ def check(dir)
93
+ raise GobstonesTypeError, "#{dir} is not a direction" \
94
+ unless [Norte, Sur, Este, Oeste].include? dir.class
95
+ end
96
+
97
+ end
98
+
99
+ end
100
+
101
+ end