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.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.simplecov +3 -0
- data/.travis.yml +4 -0
- data/CHANGELOG +4 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +47 -0
- data/LICENSE +675 -0
- data/README.md +17 -0
- data/Rakefile +4 -0
- data/bin/gobstones +12 -0
- data/gobstones.gemspec +24 -0
- data/lib/gobstones/cli/board_template +39 -0
- data/lib/gobstones/cli/printer.rb +106 -0
- data/lib/gobstones/cli/runner.rb +52 -0
- data/lib/gobstones/extensions/all.rb +2 -0
- data/lib/gobstones/extensions/boolean.rb +17 -0
- data/lib/gobstones/extensions/fixnum.rb +9 -0
- data/lib/gobstones/lang/all.rb +5 -0
- data/lib/gobstones/lang/commands/all.rb +13 -0
- data/lib/gobstones/lang/commands/assignments.rb +29 -0
- data/lib/gobstones/lang/commands/boom_cmd.rb +28 -0
- data/lib/gobstones/lang/commands/command_block.rb +37 -0
- data/lib/gobstones/lang/commands/conditional_cmd.rb +27 -0
- data/lib/gobstones/lang/commands/if_cmd.rb +38 -0
- data/lib/gobstones/lang/commands/ir_al_origen_cmd.rb +19 -0
- data/lib/gobstones/lang/commands/mover_cmd.rb +25 -0
- data/lib/gobstones/lang/commands/poner_cmd.rb +31 -0
- data/lib/gobstones/lang/commands/procedure_call.rb +23 -0
- data/lib/gobstones/lang/commands/repeat_with_cmd.rb +73 -0
- data/lib/gobstones/lang/commands/sacar_cmd.rb +31 -0
- data/lib/gobstones/lang/commands/skip_cmd.rb +19 -0
- data/lib/gobstones/lang/commands/vaciar_tablero_cmd.rb +19 -0
- data/lib/gobstones/lang/commands/while_cmd.rb +25 -0
- data/lib/gobstones/lang/definitions/all.rb +4 -0
- data/lib/gobstones/lang/definitions/definition.rb +32 -0
- data/lib/gobstones/lang/definitions/definition_call.rb +24 -0
- data/lib/gobstones/lang/definitions/function.rb +14 -0
- data/lib/gobstones/lang/definitions/main.rb +26 -0
- data/lib/gobstones/lang/definitions/no_return_statement.rb +15 -0
- data/lib/gobstones/lang/definitions/procedure.rb +44 -0
- data/lib/gobstones/lang/definitions/return_from_function.rb +22 -0
- data/lib/gobstones/lang/definitions/return_from_main.rb +22 -0
- data/lib/gobstones/lang/definitions/var_tuple.rb +26 -0
- data/lib/gobstones/lang/expressions/all.rb +8 -0
- data/lib/gobstones/lang/expressions/arithmetic_expressions.rb +52 -0
- data/lib/gobstones/lang/expressions/boolean_expressions.rb +29 -0
- data/lib/gobstones/lang/expressions/comparison_expressions.rb +45 -0
- data/lib/gobstones/lang/expressions/function_call.rb +15 -0
- data/lib/gobstones/lang/expressions/one_arg_expression.rb +21 -0
- data/lib/gobstones/lang/expressions/parentheses_expression.rb +13 -0
- data/lib/gobstones/lang/expressions/primitive_functions.rb +68 -0
- data/lib/gobstones/lang/expressions/two_arg_expression.rb +34 -0
- data/lib/gobstones/lang/expressions/type_bound_functions.rb +66 -0
- data/lib/gobstones/lang/expressions/var_name.rb +31 -0
- data/lib/gobstones/lang/literals/all.rb +4 -0
- data/lib/gobstones/lang/literals/booleans.rb +109 -0
- data/lib/gobstones/lang/literals/colors.rb +94 -0
- data/lib/gobstones/lang/literals/directions.rb +137 -0
- data/lib/gobstones/lang/literals/literal.rb +63 -0
- data/lib/gobstones/lang/literals/number.rb +49 -0
- data/lib/gobstones/lang/program.rb +32 -0
- data/lib/gobstones/modules/equal_by_class.rb +13 -0
- data/lib/gobstones/parser/ast/ast.rb +210 -0
- data/lib/gobstones/parser/grammar/gobstones.treetop +316 -0
- data/lib/gobstones/parser/parse_error.rb +17 -0
- data/lib/gobstones/parser/treetop_parser.rb +73 -0
- data/lib/gobstones/runner/all.rb +6 -0
- data/lib/gobstones/runner/board.rb +57 -0
- data/lib/gobstones/runner/cell.rb +60 -0
- data/lib/gobstones/runner/errors/all.rb +8 -0
- data/lib/gobstones/runner/errors/boom_error.rb +11 -0
- data/lib/gobstones/runner/errors/definition_not_found_error.rb +19 -0
- data/lib/gobstones/runner/errors/empty_cell_error.rb +11 -0
- data/lib/gobstones/runner/errors/gobstones_runtime_error.rb +11 -0
- data/lib/gobstones/runner/errors/gobstones_type_error.rb +11 -0
- data/lib/gobstones/runner/errors/out_of_board_error.rb +11 -0
- data/lib/gobstones/runner/errors/undefined_variable_error.rb +11 -0
- data/lib/gobstones/runner/errors/wrong_arguments_error.rb +11 -0
- data/lib/gobstones/runner/execution_context.rb +89 -0
- data/lib/gobstones/runner/head.rb +101 -0
- data/lib/gobstones/type_check_result.rb +16 -0
- data/spec/lang/commands/assignments_spec.rb +13 -0
- data/spec/lang/commands/boom_cmd_spec.rb +8 -0
- data/spec/lang/commands/cmd_block_spec.rb +21 -0
- data/spec/lang/commands/if_cmd_spec.rb +49 -0
- data/spec/lang/commands/ir_al_origen_cmd_spec.rb +16 -0
- data/spec/lang/commands/mover_cmd_spec.rb +38 -0
- data/spec/lang/commands/poner_cmd_spec.rb +29 -0
- data/spec/lang/commands/procedure_call_spec.rb +44 -0
- data/spec/lang/commands/procedure_spec.rb +67 -0
- data/spec/lang/commands/repeat_with_cmd_spec.rb +41 -0
- data/spec/lang/commands/sacar_cmd_spec.rb +34 -0
- data/spec/lang/commands/skip_cmd_spec.rb +12 -0
- data/spec/lang/commands/vaciar_tablero_cmd_spec.rb +13 -0
- data/spec/lang/commands/while_cmd_spec.rb +37 -0
- data/spec/lang/expressions/arithmetic_expressions_spec.rb +108 -0
- data/spec/lang/expressions/boolean_expressions_spec.rb +56 -0
- data/spec/lang/expressions/comparison_expressions_spec.rb +285 -0
- data/spec/lang/expressions/primitive_functions_spec.rb +126 -0
- data/spec/lang/expressions/type_bound_functions_spec.rb +39 -0
- data/spec/lang/expressions/var_name_spec.rb +16 -0
- data/spec/lang/literals/booleans_spec.rb +13 -0
- data/spec/lang/literals/colors_spec.rb +13 -0
- data/spec/lang/literals/directions_spec.rb +45 -0
- data/spec/lang/literals/numbers_spec.rb +8 -0
- data/spec/matchers/parse_matcher.rb +84 -0
- data/spec/parser/arithmetic_expressions_spec.rb +129 -0
- data/spec/parser/assignments_spec.rb +39 -0
- data/spec/parser/boolean_expressions_spec.rb +111 -0
- data/spec/parser/command_block_spec.rb +50 -0
- data/spec/parser/data_types_spec.rb +67 -0
- data/spec/parser/function_calls_spec.rb +37 -0
- data/spec/parser/function_definitions_spec.rb +50 -0
- data/spec/parser/gobstones_program_spec.rb +55 -0
- data/spec/parser/if_command_spec.rb +46 -0
- data/spec/parser/main_definition_spec.rb +42 -0
- data/spec/parser/nested_expressions_spec.rb +39 -0
- data/spec/parser/primitive_expressions_spec.rb +105 -0
- data/spec/parser/procedure_calls_spec.rb +36 -0
- data/spec/parser/procedure_definitions_spec.rb +39 -0
- data/spec/parser/repeat_with_command_spec.rb +23 -0
- data/spec/parser/simple_commands_spec.rb +62 -0
- data/spec/parser/treetop_parser_spec.rb +109 -0
- data/spec/parser/var_tuple_spec.rb +30 -0
- data/spec/parser/while_command_spec.rb +30 -0
- data/spec/runner/board_spec.rb +85 -0
- data/spec/runner/cell_spec.rb +72 -0
- data/spec/runner/execution_context_spec.rb +64 -0
- data/spec/runner/head_spec.rb +139 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/type_checker_spec.rb +37 -0
- metadata +242 -0
@@ -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,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,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,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
|