gobstones 0.0.2 → 0.0.3
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 +5 -5
- data/.rubocop.yml +133 -0
- data/.rubocop_todo.yml +75 -0
- data/.simplecov +1 -3
- data/.tool-versions +1 -0
- data/.travis.yml +9 -2
- data/Gemfile +11 -5
- data/Gemfile.lock +65 -39
- data/README.md +8 -1
- data/Rakefile +1 -1
- data/bin/gobstones +1 -1
- data/gobstones.gemspec +12 -11
- data/lib/gobstones/cli/printer.rb +41 -28
- data/lib/gobstones/cli/runner.rb +50 -15
- data/lib/gobstones/extensions/all.rb +1 -1
- data/lib/gobstones/extensions/boolean.rb +1 -5
- data/lib/gobstones/extensions/{fixnum.rb → integer.rb} +2 -4
- data/lib/gobstones/extensions/string.rb +1 -3
- data/lib/gobstones/lang/all.rb +3 -3
- data/lib/gobstones/lang/commands/all.rb +11 -10
- data/lib/gobstones/lang/commands/boom.rb +26 -0
- data/lib/gobstones/lang/commands/command_block.rb +23 -23
- data/lib/gobstones/lang/commands/conditional.rb +26 -0
- data/lib/gobstones/lang/commands/if.rb +13 -0
- data/lib/gobstones/lang/commands/if_then_else.rb +26 -0
- data/lib/gobstones/lang/commands/ir_al_origen.rb +15 -0
- data/lib/gobstones/lang/commands/mover.rb +23 -0
- data/lib/gobstones/lang/commands/multiple_assignment.rb +34 -21
- data/lib/gobstones/lang/commands/poner.rb +31 -0
- data/lib/gobstones/lang/commands/procedure_call.rb +8 -8
- data/lib/gobstones/lang/commands/repeat_with.rb +69 -0
- data/lib/gobstones/lang/commands/sacar.rb +29 -0
- data/lib/gobstones/lang/commands/single_assignment.rb +15 -20
- data/lib/gobstones/lang/commands/skip.rb +15 -0
- data/lib/gobstones/lang/commands/vaciar_tablero.rb +15 -0
- data/lib/gobstones/lang/commands/while.rb +20 -0
- data/lib/gobstones/lang/definitions/definition.rb +16 -23
- data/lib/gobstones/lang/definitions/definition_call.rb +7 -15
- data/lib/gobstones/lang/definitions/function.rb +1 -7
- data/lib/gobstones/lang/definitions/main.rb +1 -8
- data/lib/gobstones/lang/definitions/no_return_statement.rb +2 -8
- data/lib/gobstones/lang/definitions/procedure.rb +1 -7
- data/lib/gobstones/lang/definitions/return_from_function.rb +6 -13
- data/lib/gobstones/lang/definitions/return_from_main.rb +15 -10
- data/lib/gobstones/lang/definitions/var_tuple.rb +10 -12
- data/lib/gobstones/lang/expressions/arithmetic_expressions.rb +17 -27
- data/lib/gobstones/lang/expressions/boolean_expressions.rb +4 -10
- data/lib/gobstones/lang/expressions/comparison_expressions.rb +0 -16
- data/lib/gobstones/lang/expressions/enclosed_by_parens_expression.rb +3 -5
- data/lib/gobstones/lang/expressions/expression.rb +18 -0
- data/lib/gobstones/lang/expressions/function_call.rb +9 -6
- data/lib/gobstones/lang/expressions/one_arg_expression.rb +8 -16
- data/lib/gobstones/lang/expressions/primitive_functions.rb +24 -16
- data/lib/gobstones/lang/expressions/two_arg_expression.rb +9 -16
- data/lib/gobstones/lang/expressions/type_bound_functions.rb +30 -25
- data/lib/gobstones/lang/expressions/var_name.rb +9 -13
- data/lib/gobstones/lang/literals/all.rb +3 -3
- data/lib/gobstones/lang/literals/{booleans.rb → boolean.rb} +24 -22
- data/lib/gobstones/lang/literals/{colors.rb → color.rb} +4 -14
- data/lib/gobstones/lang/literals/{directions.rb → direction.rb} +3 -13
- data/lib/gobstones/lang/literals/literal.rb +35 -27
- data/lib/gobstones/lang/literals/number.rb +6 -8
- data/lib/gobstones/lang/program.rb +9 -16
- data/lib/gobstones/modules/equality_definition.rb +23 -0
- data/lib/gobstones/parser/ast/ast.rb +48 -70
- data/lib/gobstones/parser/parse_error.rb +2 -7
- data/lib/gobstones/parser/treetop_parser.rb +9 -14
- data/lib/gobstones/runner/board.rb +12 -15
- data/lib/gobstones/runner/cell.rb +14 -20
- data/lib/gobstones/runner/errors/all.rb +1 -1
- data/lib/gobstones/runner/errors/boom_error.rb +0 -5
- data/lib/gobstones/runner/errors/definition_not_found_error.rb +7 -7
- data/lib/gobstones/runner/errors/empty_cell_error.rb +0 -5
- data/lib/gobstones/runner/errors/gobstones_runtime_error.rb +0 -5
- data/lib/gobstones/runner/errors/gobstones_type_error.rb +2 -7
- data/lib/gobstones/runner/errors/out_of_board_error.rb +0 -5
- data/lib/gobstones/runner/errors/undefined_variable_error.rb +6 -4
- data/lib/gobstones/runner/errors/wrong_arguments_error.rb +0 -5
- data/lib/gobstones/runner/execution_context.rb +16 -33
- data/lib/gobstones/runner/head.rb +17 -20
- data/lib/gobstones/runner/program_result.rb +12 -0
- data/lib/gobstones/type_check_result.rb +0 -4
- data/spec/lang/commands/boom_spec.rb +7 -0
- data/spec/lang/commands/command_block_spec.rb +15 -0
- data/spec/lang/commands/if_spec.rb +32 -0
- data/spec/lang/commands/if_then_else_spec.rb +19 -0
- data/spec/lang/commands/ir_al_origen_spec.rb +11 -0
- data/spec/lang/commands/mover_spec.rb +30 -0
- data/spec/lang/commands/multiple_assignment_spec.rb +39 -22
- data/spec/lang/commands/poner_spec.rb +27 -0
- data/spec/lang/commands/procedure_call_spec.rb +26 -28
- data/spec/lang/commands/procedure_spec.rb +32 -32
- data/spec/lang/commands/repeat_with_spec.rb +64 -0
- data/spec/lang/commands/sacar_spec.rb +32 -0
- data/spec/lang/commands/single_assignment_spec.rb +5 -6
- data/spec/lang/commands/skip_spec.rb +10 -0
- data/spec/lang/commands/vaciar_tablero_spec.rb +10 -0
- data/spec/lang/commands/while_spec.rb +39 -0
- data/spec/lang/definitions/main_spec.rb +34 -0
- data/spec/lang/definitions/no_return_statement_spec.rb +4 -5
- data/spec/lang/definitions/var_tuple_spec.rb +4 -7
- data/spec/lang/expressions/arithmetic_expressions_spec.rb +37 -64
- data/spec/lang/expressions/boolean_expressions_spec.rb +25 -34
- data/spec/lang/expressions/comparison_expressions_spec.rb +109 -155
- data/spec/lang/expressions/enclosed_by_parens_expression_spec.rb +3 -7
- data/spec/lang/expressions/function_call_spec.rb +24 -20
- data/spec/lang/expressions/primitive_functions_spec.rb +28 -39
- data/spec/lang/expressions/type_bound_functions_spec.rb +10 -18
- data/spec/lang/expressions/var_name_spec.rb +8 -12
- data/spec/lang/literals/{booleans_spec.rb → boolean_spec.rb} +3 -5
- data/spec/lang/literals/color_spec.rb +19 -0
- data/spec/lang/literals/direction_spec.rb +46 -0
- data/spec/lang/literals/{numbers_spec.rb → number_spec.rb} +3 -4
- data/spec/matchers/parse_matcher.rb +9 -11
- data/spec/parser/arithmetic_expressions_spec.rb +51 -61
- data/spec/parser/assignments_spec.rb +21 -31
- data/spec/parser/boolean_expressions_spec.rb +35 -43
- data/spec/parser/command_block_spec.rb +18 -20
- data/spec/parser/data_types_spec.rb +9 -19
- data/spec/parser/function_calls_spec.rb +19 -19
- data/spec/parser/function_definitions_spec.rb +17 -22
- data/spec/parser/gobstones_program_spec.rb +30 -30
- data/spec/parser/if_command_spec.rb +19 -28
- data/spec/parser/main_definition_spec.rb +13 -16
- data/spec/parser/nested_expressions_spec.rb +20 -24
- data/spec/parser/primitive_expressions_spec.rb +33 -38
- data/spec/parser/procedure_calls_spec.rb +17 -18
- data/spec/parser/procedure_definitions_spec.rb +12 -15
- data/spec/parser/repeat_with_command_spec.rb +10 -10
- data/spec/parser/simple_commands_spec.rb +23 -37
- data/spec/parser/treetop_parser_spec.rb +87 -83
- data/spec/parser/var_tuple_spec.rb +8 -12
- data/spec/parser/while_command_spec.rb +11 -14
- data/spec/runner/board_spec.rb +28 -33
- data/spec/runner/cell_spec.rb +21 -28
- data/spec/runner/execution_context_spec.rb +18 -35
- data/spec/runner/head_spec.rb +54 -60
- data/spec/spec_helper.rb +10 -1
- data/spec/support/board_assertions.rb +18 -0
- data/spec/{gobstones_lang_test_objects.rb → support/gobstones_lang_test_objects.rb} +6 -4
- data/spec/type_checker_spec.rb +19 -25
- metadata +80 -56
- data/.ruby-version +0 -1
- data/lib/gobstones/lang/commands/boom_cmd.rb +0 -31
- data/lib/gobstones/lang/commands/conditional_cmd.rb +0 -31
- data/lib/gobstones/lang/commands/if_cmd.rb +0 -38
- data/lib/gobstones/lang/commands/ir_al_origen_cmd.rb +0 -19
- data/lib/gobstones/lang/commands/mover_cmd.rb +0 -27
- data/lib/gobstones/lang/commands/poner_cmd.rb +0 -35
- data/lib/gobstones/lang/commands/repeat_with_cmd.rb +0 -77
- data/lib/gobstones/lang/commands/sacar_cmd.rb +0 -33
- data/lib/gobstones/lang/commands/skip_cmd.rb +0 -19
- data/lib/gobstones/lang/commands/vaciar_tablero_cmd.rb +0 -19
- data/lib/gobstones/lang/commands/while_cmd.rb +0 -25
- data/lib/gobstones/modules/equal_by_class.rb +0 -13
- data/spec/lang/commands/boom_cmd_spec.rb +0 -8
- data/spec/lang/commands/cmd_block_spec.rb +0 -21
- data/spec/lang/commands/if_cmd_spec.rb +0 -50
- data/spec/lang/commands/ir_al_origen_cmd_spec.rb +0 -16
- data/spec/lang/commands/mover_cmd_spec.rb +0 -36
- data/spec/lang/commands/poner_cmd_spec.rb +0 -28
- data/spec/lang/commands/repeat_with_cmd_spec.rb +0 -60
- data/spec/lang/commands/sacar_cmd_spec.rb +0 -35
- data/spec/lang/commands/skip_cmd_spec.rb +0 -12
- data/spec/lang/commands/vaciar_tablero_cmd_spec.rb +0 -14
- data/spec/lang/commands/while_cmd_spec.rb +0 -43
- data/spec/lang/literals/colors_spec.rb +0 -13
- data/spec/lang/literals/directions_spec.rb +0 -45
@@ -0,0 +1,64 @@
|
|
1
|
+
RSpec.describe RepeatWith do
|
2
|
+
let(:context) { clean_context }
|
3
|
+
let(:var_name) { 'var'.to_var_name }
|
4
|
+
|
5
|
+
it 'iterates over numbers when evaluating' do
|
6
|
+
command_block = CommandBlock.with_just(Poner.new(rojo))
|
7
|
+
repeat_with = described_class.new(var_name, 1.to_gbs_num, 10.to_gbs_num, command_block)
|
8
|
+
|
9
|
+
repeat_with.evaluate context
|
10
|
+
|
11
|
+
expect(context.head.number_of_balls(rojo)).to eq(10)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'raises an error if the range values have not the same type' do
|
15
|
+
repeat_with = described_class.new(var_name, 1.to_gbs_num, este, empty_body)
|
16
|
+
|
17
|
+
expect { repeat_with.evaluate context }.
|
18
|
+
to raise_error(GobstonesTypeError, /types don't match in range values/)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'raises an error if the index variable is previously defined' do
|
22
|
+
repeat_with = described_class.new(var_name, 1.to_gbs_num, 5.to_gbs_num, empty_body)
|
23
|
+
|
24
|
+
context.set var_name, 42.to_gbs_num
|
25
|
+
|
26
|
+
expect { repeat_with.evaluate context }.
|
27
|
+
to raise_error(GobstonesRuntimeError, /index variable can't be used because it's already defined/)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'removes the index variable assignment after execution' do
|
31
|
+
repeat_with = described_class.new(var_name, azul, verde, empty_body)
|
32
|
+
|
33
|
+
repeat_with.evaluate context
|
34
|
+
|
35
|
+
expect(context.has_variable_named?('var')).to be(false)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'allows to use the index variable inside the command block' do
|
39
|
+
cmd_block = CommandBlock.with_just(Poner.new(var_name))
|
40
|
+
repeat_with = described_class.new(var_name, azul, verde, cmd_block)
|
41
|
+
|
42
|
+
repeat_with.evaluate context
|
43
|
+
|
44
|
+
expect_balls(azul, negro, rojo, verde)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'does exactly one iteration if range values are the same' do
|
48
|
+
cmd_block = CommandBlock.with_just(Poner.new(verde))
|
49
|
+
repeat_with = described_class.new(var_name, 1.to_gbs_num, 1.to_gbs_num, cmd_block)
|
50
|
+
|
51
|
+
repeat_with.evaluate context
|
52
|
+
|
53
|
+
expect_balls(verde)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'does no iterations if the from is higher than the to' do
|
57
|
+
cmd_block = CommandBlock.with_just(Poner.new(verde))
|
58
|
+
repeat_with = described_class.new(var_name, 8.to_gbs_num, 4.to_gbs_num, cmd_block)
|
59
|
+
|
60
|
+
repeat_with.evaluate context
|
61
|
+
|
62
|
+
expect_no_balls(verde)
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
RSpec.describe Sacar do
|
2
|
+
let(:context) { clean_context }
|
3
|
+
|
4
|
+
it 'takes off balls from the board when evaluating' do
|
5
|
+
3.times { context.head.put rojo }
|
6
|
+
|
7
|
+
described_class.new(rojo).evaluate context
|
8
|
+
|
9
|
+
expect(context.head.number_of_balls(rojo)).to eq(2)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'undoes a command' do
|
13
|
+
described_class.new(rojo).undo context
|
14
|
+
|
15
|
+
expect(context.head.number_of_balls(rojo)).to eq(1)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns the opposite command' do
|
19
|
+
opposite_command = described_class.new(rojo).opposite
|
20
|
+
|
21
|
+
expect(opposite_command).to eq(Poner.new(rojo))
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'fails if there are no balls in the board' do
|
25
|
+
expect { described_class.new(rojo).evaluate(context) }.to raise_error(EmptyCellError)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'fails if the argument is not a color' do
|
29
|
+
expect { described_class.new(true_value).evaluate(context) }.
|
30
|
+
to raise_error(GobstonesTypeError, /is not a color/)
|
31
|
+
end
|
32
|
+
end
|
@@ -1,13 +1,12 @@
|
|
1
|
-
describe SingleAssignment do
|
2
|
-
|
1
|
+
RSpec.describe SingleAssignment do
|
3
2
|
let(:context) { clean_context }
|
4
3
|
let(:a) { 'a'.to_var_name }
|
5
4
|
|
6
|
-
it
|
7
|
-
assign =
|
5
|
+
it 'evaluates the associated expression to the var name' do
|
6
|
+
assign = described_class.new(a, Add.new(3.to_gbs_num, 4.to_gbs_num))
|
8
7
|
assign.evaluate context
|
9
|
-
|
8
|
+
|
9
|
+
expect(context.has_variable_named?('a')).to be(true)
|
10
10
|
expect(context.get(a)).to eq(7.to_gbs_num)
|
11
11
|
end
|
12
|
-
|
13
12
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
RSpec.describe While do
|
2
|
+
let(:context) { clean_context }
|
3
|
+
let(:while_block) { CommandBlock.with_just(Poner.new(verde)) }
|
4
|
+
|
5
|
+
def stub_condition(times)
|
6
|
+
instance_double(Boolean).tap do |condition|
|
7
|
+
expected_values = [true_value] * times + [false_value]
|
8
|
+
allow(condition).to receive(:evaluate).and_return(*expected_values)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'evaluates the command block until the condition is not satisfied' do
|
13
|
+
while_cmd = described_class.new(stub_condition(3), while_block)
|
14
|
+
|
15
|
+
while_cmd.evaluate context
|
16
|
+
|
17
|
+
expect(context.head.number_of_balls(verde)).to eq(3)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'does not evaluate the command block if the condition is false' do
|
21
|
+
while_cmd = described_class.new(stub_condition(0), while_block)
|
22
|
+
|
23
|
+
while_cmd.evaluate context
|
24
|
+
|
25
|
+
expect_no_balls(verde)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'fails with type error if the condition is not boolean' do
|
29
|
+
while_cmd = described_class.new(sur, while_block)
|
30
|
+
|
31
|
+
expect { while_cmd.evaluate context }.to raise_error(GobstonesTypeError, /is not a boolean/)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'fails with stack overflow if the condition is always true' do
|
35
|
+
while_cmd = described_class.new(true_value, while_block)
|
36
|
+
|
37
|
+
expect { while_cmd.evaluate context }.to raise_error(GobstonesRuntimeError, /stack overflow/)
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
RSpec.describe Main do
|
2
|
+
subject(:if_evaluation) { main.evaluate(context) }
|
3
|
+
|
4
|
+
let(:context) { clean_context }
|
5
|
+
let(:return_tuple) { VarTuple.with_names(%w[x y]) }
|
6
|
+
let(:return_from_main) { ReturnFromMain.new(return_tuple) }
|
7
|
+
let(:assign_x) { SingleAssignment.new('x'.to_var_name, 42.to_gbs_num) }
|
8
|
+
let(:assign_y) { SingleAssignment.new('y'.to_var_name, verde) }
|
9
|
+
let(:command_block) { CommandBlock.new([assign_x, assign_y]) }
|
10
|
+
let(:main) { described_class.new(command_block, return_from_main) }
|
11
|
+
|
12
|
+
it 'evaluates the body' do
|
13
|
+
if_evaluation
|
14
|
+
|
15
|
+
%w[x y].each { |var_name| expect(context).to have_variable_named(var_name) }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with return statement' do
|
19
|
+
it 'returns its return value, if there is one' do
|
20
|
+
expect(if_evaluation).to eq(
|
21
|
+
'x'.to_var_name => 42.to_gbs_num,
|
22
|
+
'y'.to_var_name => verde,
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'without return statement' do
|
28
|
+
let(:return_from_main) { no_return_statement }
|
29
|
+
|
30
|
+
it 'returns an empty result when no return statement is present' do
|
31
|
+
expect(if_evaluation).to be_empty
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,10 +1,9 @@
|
|
1
|
-
describe NoReturnStatement do
|
1
|
+
RSpec.describe NoReturnStatement do
|
2
|
+
subject(:no_return_statement) { described_class.new }
|
2
3
|
|
3
4
|
let(:context) { clean_context }
|
4
|
-
let(:no_return_statement) { NoReturnStatement.new }
|
5
5
|
|
6
|
-
it
|
7
|
-
expect { no_return_statement.evaluate
|
6
|
+
it 'does nothing when evaluating on a context' do
|
7
|
+
expect { no_return_statement.evaluate(context) }.not_to change(context, :head)
|
8
8
|
end
|
9
|
-
|
10
9
|
end
|
@@ -1,16 +1,13 @@
|
|
1
|
-
describe VarTuple do
|
1
|
+
RSpec.describe VarTuple do
|
2
|
+
let(:var_tuple) { described_class.with_names(%w[a b c]) }
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
it "returns its length" do
|
4
|
+
it 'returns its length' do
|
6
5
|
expect(var_tuple.length).to eq(3)
|
7
6
|
end
|
8
7
|
|
9
|
-
it
|
8
|
+
it 'returns a variable at a given index' do
|
10
9
|
expect(var_tuple.variable_at(0)).to eq('a'.to_var_name)
|
11
10
|
expect(var_tuple.variable_at(1)).to eq('b'.to_var_name)
|
12
11
|
expect(var_tuple.variable_at(2)).to eq('c'.to_var_name)
|
13
|
-
|
14
12
|
end
|
15
|
-
|
16
13
|
end
|
@@ -1,108 +1,81 @@
|
|
1
|
-
describe
|
2
|
-
|
1
|
+
RSpec.describe 'arithmetic expressions' do
|
3
2
|
describe Add do
|
4
|
-
|
5
|
-
|
6
|
-
add = Add.new(42.to_gbs_num, 23.to_gbs_num)
|
7
|
-
expect(add.evaluate).to eq(65.to_gbs_num)
|
3
|
+
it 'evaluates with two numbers' do
|
4
|
+
expect(described_class.numbers(42, 23).evaluate).to eq(65.to_gbs_num)
|
8
5
|
end
|
9
6
|
|
10
|
-
it
|
11
|
-
add_4_8 =
|
12
|
-
add_12_15 =
|
13
|
-
add_27_16 =
|
14
|
-
add_43_23 =
|
15
|
-
add_66_42 =
|
7
|
+
it 'evaluates nested add expressions' do
|
8
|
+
add_4_8 = described_class.numbers(4, 8)
|
9
|
+
add_12_15 = described_class.new(add_4_8, 15.to_gbs_num)
|
10
|
+
add_27_16 = described_class.new(add_12_15, 16.to_gbs_num)
|
11
|
+
add_43_23 = described_class.new(add_27_16, 23.to_gbs_num)
|
12
|
+
add_66_42 = described_class.new(add_43_23, 42.to_gbs_num)
|
16
13
|
|
17
14
|
expect(add_66_42.evaluate).to eq(108.to_gbs_num)
|
18
15
|
end
|
19
|
-
|
20
16
|
end
|
21
17
|
|
22
18
|
describe Sub do
|
23
|
-
|
24
|
-
|
25
|
-
sub = Sub.new(42.to_gbs_num, 15.to_gbs_num)
|
26
|
-
expect(sub.evaluate).to eq(27.to_gbs_num)
|
19
|
+
it 'evaluates with two numbers' do
|
20
|
+
expect(described_class.numbers(42, 15).evaluate).to eq(27.to_gbs_num)
|
27
21
|
end
|
28
22
|
|
29
|
-
it
|
30
|
-
|
31
|
-
expect(sub.evaluate).to eq(-27.to_gbs_num)
|
23
|
+
it 'evaluates returning a negative result' do
|
24
|
+
expect(described_class.numbers(15, 42).evaluate).to eq(-27.to_gbs_num)
|
32
25
|
end
|
33
26
|
|
34
|
-
it
|
35
|
-
sub_n1_n2 =
|
36
|
-
sub =
|
27
|
+
it 'evaluates nested sub expressions' do
|
28
|
+
sub_n1_n2 = described_class.numbers(42, 15)
|
29
|
+
sub = described_class.new(sub_n1_n2, 8.to_gbs_num)
|
37
30
|
|
38
31
|
expect(sub.evaluate).to eq(19.to_gbs_num)
|
39
32
|
end
|
40
|
-
|
41
33
|
end
|
42
34
|
|
43
35
|
describe Mul do
|
44
|
-
|
45
|
-
|
46
|
-
mul = Mul.new(4.to_gbs_num, 8.to_gbs_num)
|
47
|
-
expect(mul.evaluate).to eq(32.to_gbs_num)
|
36
|
+
it 'evaluates a simple mul' do
|
37
|
+
expect(described_class.numbers(4, 8).evaluate).to eq(32.to_gbs_num)
|
48
38
|
end
|
49
39
|
|
50
|
-
it
|
51
|
-
mul =
|
52
|
-
expect(Mul.new(mul, 5.to_gbs_num).evaluate).to eq(-40.to_gbs_num)
|
53
|
-
end
|
40
|
+
it 'evaluates a nested mul expression' do
|
41
|
+
mul = described_class.numbers(-2, 4)
|
54
42
|
|
43
|
+
expect(described_class.new(mul, 5.to_gbs_num).evaluate).to eq(-40.to_gbs_num)
|
44
|
+
end
|
55
45
|
end
|
56
46
|
|
57
47
|
describe Div do
|
58
|
-
|
59
|
-
|
60
|
-
div = Div.new(12.to_gbs_num, 3.to_gbs_num)
|
61
|
-
expect(div.evaluate).to eq(4.to_gbs_num)
|
48
|
+
it 'evaluates a simple div' do
|
49
|
+
expect(described_class.numbers(12, 3).evaluate).to eq(4.to_gbs_num)
|
62
50
|
end
|
63
51
|
|
64
|
-
it
|
65
|
-
|
66
|
-
expect(div.evaluate).to eq(3.to_gbs_num)
|
52
|
+
it 'evaluates to an integer division' do
|
53
|
+
expect(described_class.numbers(10, 3).evaluate).to eq(3.to_gbs_num)
|
67
54
|
end
|
68
55
|
|
69
|
-
it
|
70
|
-
expect {
|
71
|
-
Div.new(42.to_gbs_num, 0.to_gbs_num).evaluate
|
72
|
-
}.to raise_error(GobstonesRuntimeError, 'zero division')
|
56
|
+
it 'raises an error when dividing by zero' do
|
57
|
+
expect { described_class.numbers(42, 0).evaluate }.to raise_error(GobstonesRuntimeError, 'zero division')
|
73
58
|
end
|
74
|
-
|
75
59
|
end
|
76
60
|
|
77
61
|
describe Mod do
|
78
|
-
|
79
|
-
|
80
|
-
mod = Mod.new(4.to_gbs_num, 4.to_gbs_num)
|
81
|
-
expect(mod.evaluate).to eq(0.to_gbs_num)
|
62
|
+
it 'evaluates a mod with result 0' do
|
63
|
+
expect(described_class.numbers(4, 4).evaluate).to eq(0.to_gbs_num)
|
82
64
|
end
|
83
65
|
|
84
|
-
it
|
85
|
-
|
86
|
-
expect(mod.evaluate).to eq(1.to_gbs_num)
|
66
|
+
it 'evaluates a mod with result > 0' do
|
67
|
+
expect(described_class.numbers(10, 3).evaluate).to eq(1.to_gbs_num)
|
87
68
|
end
|
88
|
-
|
89
69
|
end
|
90
70
|
|
91
71
|
describe Pow do
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
pow_42 = Pow.new(42.to_gbs_num, 0.to_gbs_num)
|
96
|
-
|
97
|
-
expect(pow_1.evaluate).to eq(1.to_gbs_num)
|
98
|
-
expect(pow_42.evaluate).to eq(1.to_gbs_num)
|
72
|
+
it 'returns 1 as a result if the power is 0' do
|
73
|
+
expect(described_class.numbers(1, 0).evaluate).to eq(1.to_gbs_num)
|
74
|
+
expect(described_class.numbers(42, 0).evaluate).to eq(1.to_gbs_num)
|
99
75
|
end
|
100
76
|
|
101
|
-
it
|
102
|
-
|
103
|
-
expect(pow.evaluate).to eq(16.to_gbs_num)
|
77
|
+
it 'evaluates 2 raised to 4' do
|
78
|
+
expect(described_class.numbers(2, 4).evaluate).to eq(16.to_gbs_num)
|
104
79
|
end
|
105
|
-
|
106
80
|
end
|
107
|
-
|
108
81
|
end
|
@@ -1,66 +1,57 @@
|
|
1
1
|
# TODO test/implement short-circuit?
|
2
|
-
describe
|
3
|
-
|
2
|
+
RSpec.describe 'evaluating boolean expressions' do
|
4
3
|
let(:context) { clean_context }
|
5
4
|
|
6
5
|
describe And do
|
7
|
-
|
8
|
-
|
9
|
-
expect(
|
10
|
-
expect(
|
11
|
-
expect(
|
12
|
-
expect(And.new(true_value, true_value).evaluate(context)).to eq(true_value)
|
6
|
+
it 'evaluates a simple and expression' do
|
7
|
+
expect(described_class.new(false_value, false_value).evaluate(context)).to eq(false_value)
|
8
|
+
expect(described_class.new(false_value, true_value).evaluate(context)).to eq(false_value)
|
9
|
+
expect(described_class.new(true_value, false_value).evaluate(context)).to eq(false_value)
|
10
|
+
expect(described_class.new(true_value, true_value).evaluate(context)).to eq(true_value)
|
13
11
|
end
|
14
|
-
|
15
12
|
end
|
16
13
|
|
17
14
|
describe Or do
|
18
|
-
|
19
|
-
|
20
|
-
expect(
|
21
|
-
expect(
|
22
|
-
expect(
|
23
|
-
expect(Or.new(true_value, true_value).evaluate(context)).to eq(true_value)
|
15
|
+
it 'evaluates a simple or expression' do
|
16
|
+
expect(described_class.new(false_value, false_value).evaluate(context)).to eq(false_value)
|
17
|
+
expect(described_class.new(false_value, true_value).evaluate(context)).to eq(true_value)
|
18
|
+
expect(described_class.new(true_value, false_value).evaluate(context)).to eq(true_value)
|
19
|
+
expect(described_class.new(true_value, true_value).evaluate(context)).to eq(true_value)
|
24
20
|
end
|
25
|
-
|
26
21
|
end
|
27
22
|
|
28
23
|
describe Not do
|
29
|
-
|
30
|
-
|
31
|
-
expect(
|
32
|
-
expect(Not.new(true_value).evaluate(context)).to eq(false_value)
|
24
|
+
it 'evaluates a simple not expression' do
|
25
|
+
expect(described_class.new(false_value).evaluate(context)).to eq(true_value)
|
26
|
+
expect(described_class.new(true_value).evaluate(context)).to eq(false_value)
|
33
27
|
end
|
34
28
|
|
35
|
-
it
|
36
|
-
expect(
|
37
|
-
expect(
|
29
|
+
it 'evaluates a double negated expression' do
|
30
|
+
expect(described_class.new(described_class.new(false_value)).evaluate(context)).to eq(false_value)
|
31
|
+
expect(described_class.new(described_class.new(true_value)).evaluate(context)).to eq(true_value)
|
38
32
|
end
|
39
33
|
|
40
|
-
it
|
41
|
-
expect {
|
34
|
+
it 'fails if the argument is not a boolean' do
|
35
|
+
expect { described_class.new(42.to_gbs_num).evaluate(context) }.
|
42
36
|
to raise_error(GobstonesTypeError, /is not a boolean/)
|
43
|
-
expect {
|
37
|
+
expect { described_class.new(azul).evaluate(context) }.
|
44
38
|
to raise_error(GobstonesTypeError, /is not a boolean/)
|
45
|
-
expect {
|
39
|
+
expect { described_class.new(oeste).evaluate(context) }.
|
46
40
|
to raise_error(GobstonesTypeError, /is not a boolean/)
|
47
41
|
end
|
48
|
-
|
49
42
|
end
|
50
43
|
|
51
|
-
describe
|
52
|
-
|
44
|
+
describe 'nested' do
|
53
45
|
it "evaluates and's and or's" do
|
54
|
-
expression = And.new
|
46
|
+
expression = And.new(Or.new(false_value, true_value), true_value)
|
55
47
|
|
56
48
|
expect(expression.evaluate(context)).to eq(true_value)
|
57
49
|
end
|
58
50
|
|
59
51
|
it "evaluates and's, or's, and not's" do
|
60
|
-
expression = Not.new
|
52
|
+
expression = Not.new(Or.new(false_value, And.new(true_value, true_value)))
|
53
|
+
|
61
54
|
expect(expression.evaluate(context)).to eq(false_value)
|
62
55
|
end
|
63
|
-
|
64
56
|
end
|
65
|
-
|
66
57
|
end
|