gobstones 0.0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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