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