gobstones 0.0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,25 @@
|
|
1
|
+
require 'gobstones/lang/expressions/one_arg_expression'
|
2
|
+
|
3
|
+
module Gobstones
|
4
|
+
|
5
|
+
module Lang
|
6
|
+
|
7
|
+
class Mover < OneArgExpression
|
8
|
+
|
9
|
+
def evaluate(context)
|
10
|
+
context.head.move arg.evaluate(context)
|
11
|
+
end
|
12
|
+
|
13
|
+
def undo(context)
|
14
|
+
opposite.evaluate context
|
15
|
+
end
|
16
|
+
|
17
|
+
def opposite
|
18
|
+
Mover.new arg.opposite
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'gobstones/lang/expressions/one_arg_expression'
|
2
|
+
require 'gobstones/lang/commands/sacar_cmd'
|
3
|
+
require 'gobstones/runner/errors/gobstones_type_error'
|
4
|
+
|
5
|
+
module Gobstones
|
6
|
+
|
7
|
+
module Lang
|
8
|
+
|
9
|
+
class Poner < OneArgExpression
|
10
|
+
|
11
|
+
def evaluate(context)
|
12
|
+
context.head.put arg.evaluate(context)
|
13
|
+
rescue RuntimeError => e
|
14
|
+
raise Gobstones::Runner::GobstonesTypeError, e.message
|
15
|
+
end
|
16
|
+
|
17
|
+
def undo(context)
|
18
|
+
# TODO maybe the command should use the original context
|
19
|
+
# instead of this one (when it was executed)
|
20
|
+
context.head.take_out arg.evaluate(context)
|
21
|
+
end
|
22
|
+
|
23
|
+
def opposite
|
24
|
+
Sacar.new arg
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'gobstones/lang/definitions/definition_call'
|
2
|
+
require 'gobstones/runner/errors/definition_not_found_error'
|
3
|
+
|
4
|
+
module Gobstones
|
5
|
+
|
6
|
+
module Lang
|
7
|
+
|
8
|
+
class ProcedureCall
|
9
|
+
|
10
|
+
include DefinitionCall
|
11
|
+
|
12
|
+
def evaluate(context)
|
13
|
+
evaluated_args = args.map { |arg| arg.evaluate context }
|
14
|
+
context.program_context.definition_named(name, ->(definition) {
|
15
|
+
definition.evaluate context, evaluated_args
|
16
|
+
}, -> { raise Gobstones::Runner::DefinitionNotFound.new name } )
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'gobstones/lang/commands/assignments'
|
2
|
+
require 'gobstones/lang/commands/command_block'
|
3
|
+
require 'gobstones/lang/commands/while_cmd'
|
4
|
+
require 'gobstones/lang/expressions/comparison_expressions'
|
5
|
+
require 'gobstones/lang/expressions/primitive_functions'
|
6
|
+
require 'gobstones/runner/errors/gobstones_runtime_error'
|
7
|
+
require 'gobstones/runner/errors/gobstones_type_error'
|
8
|
+
|
9
|
+
module Gobstones
|
10
|
+
|
11
|
+
module Lang
|
12
|
+
|
13
|
+
class RepeatWithCmd
|
14
|
+
|
15
|
+
attr_reader :var_name, :range_min, :range_max, :cmd_block
|
16
|
+
|
17
|
+
def initialize(var_name, range_min, range_max, cmd_block)
|
18
|
+
@var_name = var_name
|
19
|
+
@range_min = range_min
|
20
|
+
@range_max = range_max
|
21
|
+
@cmd_block = cmd_block
|
22
|
+
end
|
23
|
+
|
24
|
+
def ==(other)
|
25
|
+
self.class == other.class &&
|
26
|
+
self.var_name == other.var_name &&
|
27
|
+
self.range_min == other.range_min &&
|
28
|
+
self.range_max == other.range_max &&
|
29
|
+
self.cmd_block == other.cmd_block
|
30
|
+
end
|
31
|
+
|
32
|
+
def evaluate(context)
|
33
|
+
validate_range_values context
|
34
|
+
validate_index_variable_not_defined context
|
35
|
+
while_based_equivalent_cmd.evaluate context
|
36
|
+
clear_index_variable_from context
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def clear_index_variable_from(context)
|
42
|
+
context.clear var_name
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_range_values(context)
|
46
|
+
raise Gobstones::Runner::GobstonesTypeError, "types don't match in range values" \
|
47
|
+
unless range_min.evaluate(context).same_type_as(range_max.evaluate(context))
|
48
|
+
end
|
49
|
+
|
50
|
+
def validate_index_variable_not_defined(context)
|
51
|
+
raise Gobstones::Runner::GobstonesRuntimeError, "index variable can't be used because it's already defined" \
|
52
|
+
if context.has_variable_named?(var_name.name)
|
53
|
+
end
|
54
|
+
|
55
|
+
def while_based_equivalent_cmd
|
56
|
+
#
|
57
|
+
# repeatWith var in min..max block
|
58
|
+
# is equivalent to
|
59
|
+
# { var := min; while (var < max) { block; var := siguiente(var) }; block }
|
60
|
+
#
|
61
|
+
assign_cmd = SingleAssignment.new var_name, range_min
|
62
|
+
while_cond = LessThan.new var_name, range_max
|
63
|
+
increment = SingleAssignment.new var_name, Siguiente.new(var_name)
|
64
|
+
while_block = CmdBlock.new [cmd_block, increment]
|
65
|
+
while_cmd = WhileCmd.new while_cond, while_block
|
66
|
+
CmdBlock.new [assign_cmd, while_cmd, cmd_block]
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'gobstones/lang/expressions/one_arg_expression'
|
2
|
+
require 'gobstones/lang/commands/poner_cmd'
|
3
|
+
require 'gobstones/runner/errors/gobstones_type_error'
|
4
|
+
|
5
|
+
module Gobstones
|
6
|
+
|
7
|
+
module Lang
|
8
|
+
|
9
|
+
class Sacar < OneArgExpression
|
10
|
+
|
11
|
+
def evaluate(context)
|
12
|
+
begin
|
13
|
+
context.head.take_out arg.evaluate(context)
|
14
|
+
rescue RuntimeError => e
|
15
|
+
raise Gobstones::Runner::GobstonesTypeError, e.message
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def undo(context)
|
20
|
+
context.head.put arg.evaluate(context)
|
21
|
+
end
|
22
|
+
|
23
|
+
def opposite
|
24
|
+
Poner.new arg
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'gobstones/lang/commands/conditional_cmd'
|
2
|
+
require 'gobstones/runner/errors/gobstones_runtime_error'
|
3
|
+
|
4
|
+
module Gobstones
|
5
|
+
|
6
|
+
module Lang
|
7
|
+
|
8
|
+
class WhileCmd < ConditionalCmd
|
9
|
+
|
10
|
+
STACK_LIMIT = 10000
|
11
|
+
|
12
|
+
def evaluate(context)
|
13
|
+
stack_acc = 0
|
14
|
+
while evaluate_condition(context).is_true?
|
15
|
+
raise Gobstones::Runner::GobstonesRuntimeError, 'stack overflow' if stack_acc == STACK_LIMIT
|
16
|
+
then_block.evaluate context
|
17
|
+
stack_acc += 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Gobstones
|
2
|
+
|
3
|
+
module Lang
|
4
|
+
|
5
|
+
class Definition
|
6
|
+
|
7
|
+
attr_reader :name, :args, :body, :return_statement
|
8
|
+
|
9
|
+
def initialize(name, args, body, return_statement)
|
10
|
+
@name = name
|
11
|
+
@args = args
|
12
|
+
@body = body
|
13
|
+
@return_statement = return_statement
|
14
|
+
end
|
15
|
+
|
16
|
+
def ==(other)
|
17
|
+
self.class == other.class &&
|
18
|
+
self.name == other.name &&
|
19
|
+
self.args == other.args &&
|
20
|
+
self.body == other.body &&
|
21
|
+
self.return_statement == other.return_statement
|
22
|
+
end
|
23
|
+
|
24
|
+
def named?(a_name)
|
25
|
+
name == a_name
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Gobstones
|
2
|
+
|
3
|
+
module Lang
|
4
|
+
|
5
|
+
module DefinitionCall
|
6
|
+
|
7
|
+
attr_reader :name, :args
|
8
|
+
|
9
|
+
def initialize(name, args=[])
|
10
|
+
@name = name
|
11
|
+
@args = args
|
12
|
+
end
|
13
|
+
|
14
|
+
def ==(other)
|
15
|
+
self.class == other.class &&
|
16
|
+
self.name == other.name &&
|
17
|
+
self.args == other.args
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'gobstones/lang/definitions/definition'
|
2
|
+
require 'gobstones/lang/definitions/var_tuple'
|
3
|
+
require 'gobstones/lang/definitions/no_return_statement'
|
4
|
+
require 'gobstones/lang/definitions/return_from_main'
|
5
|
+
|
6
|
+
module Gobstones
|
7
|
+
|
8
|
+
module Lang
|
9
|
+
|
10
|
+
class Main < Definition
|
11
|
+
|
12
|
+
def initialize(body, return_statement)
|
13
|
+
super('Main', VarTuple.new([]), body, return_statement)
|
14
|
+
end
|
15
|
+
|
16
|
+
def evaluate(context)
|
17
|
+
# evaluate body
|
18
|
+
body.evaluate context
|
19
|
+
# evaluate return
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'gobstones/lang/definitions/definition'
|
2
|
+
require 'gobstones/lang/definitions/no_return_statement'
|
3
|
+
require 'gobstones/runner/execution_context'
|
4
|
+
require 'gobstones/runner/errors/wrong_arguments_error'
|
5
|
+
|
6
|
+
module Gobstones
|
7
|
+
|
8
|
+
module Lang
|
9
|
+
|
10
|
+
class Procedure < Definition
|
11
|
+
|
12
|
+
# TODO rename args to a better name, args_tuple?
|
13
|
+
|
14
|
+
def initialize(name, args, body)
|
15
|
+
super(name, args, body, NoReturnStatement.new)
|
16
|
+
end
|
17
|
+
|
18
|
+
def evaluate(context, arguments=[])
|
19
|
+
check_number_of_arguments arguments
|
20
|
+
procedure_context = Gobstones::Runner::ProcedureExecutionContext.based_on context
|
21
|
+
set_arguments arguments, procedure_context
|
22
|
+
body.evaluate procedure_context
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def check_number_of_arguments(arguments)
|
28
|
+
if args.length != arguments.length
|
29
|
+
message = "Wrong number of arguments in procedure '#{name}': expected #{args.length}, got #{arguments.length}"
|
30
|
+
raise Gobstones::Runner::WrongArgumentsError, message
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_arguments(arguments, procedure_context)
|
35
|
+
args.length.times do |index|
|
36
|
+
procedure_context.set args.variables[index], arguments[index]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|