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
| @@ -1,53 +1,43 @@ | |
| 1 | 
            -
            describe Gobstones::Parser,  | 
| 1 | 
            +
            RSpec.describe Gobstones::Parser, 'assignments' do
         | 
| 2 | 
            +
              describe 'single' do
         | 
| 3 | 
            +
                it 'parses a valid assignment with a simple expression' do
         | 
| 4 | 
            +
                  assignment = SingleAssignment.new('myDir'.to_var_name, norte)
         | 
| 2 5 |  | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
                it "parses a valid assignment with a simple expression" do
         | 
| 6 | 
            -
                  assignment = SingleAssignment.new 'myDir'.to_var_name, norte
         | 
| 7 | 
            -
             | 
| 8 | 
            -
                  expect('myDir:=Norte').
         | 
| 9 | 
            -
                    to be_parsed_as(:command).and_return(assignment)
         | 
| 10 | 
            -
                  expect('myDir  :=   Norte').
         | 
| 11 | 
            -
                    to be_parsed_as(:command).and_return(assignment)
         | 
| 6 | 
            +
                  expect('myDir:=Norte').to be_parsed_as(:command).and_return(assignment)
         | 
| 7 | 
            +
                  expect('myDir  :=   Norte').to be_parsed_as(:command).and_return(assignment)
         | 
| 12 8 | 
             
                end
         | 
| 13 9 |  | 
| 14 | 
            -
                it  | 
| 15 | 
            -
                  a | 
| 16 | 
            -
                   | 
| 17 | 
            -
                   | 
| 10 | 
            +
                it 'parses a valid assignment with a complex expression' do
         | 
| 11 | 
            +
                  a = 'a'.to_var_name
         | 
| 12 | 
            +
                  b = 'b'.to_var_name
         | 
| 13 | 
            +
                  exp = Or.new(false_value, EnclosedByParensExpression.new(And.new(a, b)))
         | 
| 14 | 
            +
                  assignment = SingleAssignment.new('myVar'.to_var_name, exp)
         | 
| 18 15 |  | 
| 19 | 
            -
                  expect('myVar := False || (a && b)').
         | 
| 20 | 
            -
                    to be_parsed_as(:command).and_return(assignment)
         | 
| 16 | 
            +
                  expect('myVar := False || (a && b)').to be_parsed_as(:command).and_return(assignment)
         | 
| 21 17 | 
             
                end
         | 
| 22 18 |  | 
| 23 | 
            -
                it  | 
| 19 | 
            +
                it 'does not parse with an invalid var name' do
         | 
| 24 20 | 
             
                  expect('MyWrongVar := a').to be_parsed_as(:command).and_fail
         | 
| 25 21 | 
             
                end
         | 
| 26 22 |  | 
| 27 | 
            -
                it  | 
| 23 | 
            +
                it 'does not parse with a command on the right side' do
         | 
| 28 24 | 
             
                  expect('myVar := Skip').to be_parsed_as(:command).and_fail
         | 
| 29 25 | 
             
                end
         | 
| 30 | 
            -
             | 
| 31 26 | 
             
              end
         | 
| 32 27 |  | 
| 33 | 
            -
              describe  | 
| 34 | 
            -
             | 
| 35 | 
            -
                context "failures" do
         | 
| 36 | 
            -
             | 
| 28 | 
            +
              describe 'multiple' do
         | 
| 29 | 
            +
                context 'when input causes a failure' do
         | 
| 37 30 | 
             
                  it 'fails if the expression on the left side is not a var tuple' do
         | 
| 38 31 | 
             
                    expect('myVar = funcCall()').to be_parsed_as(:command).and_fail
         | 
| 39 32 | 
             
                  end
         | 
| 40 | 
            -
             | 
| 41 33 | 
             
                end
         | 
| 42 34 |  | 
| 43 35 | 
             
                it 'parses a valid assignment with a function call on the right side' do
         | 
| 44 | 
            -
                  var_tuple = VarTuple. | 
| 45 | 
            -
                  func_call = FunctionCall.new | 
| 46 | 
            -
                  assignment = MultipleAssignment.new | 
| 47 | 
            -
                  expect('(aColor, aDirection) := myFunction()').
         | 
| 48 | 
            -
                      to be_parsed_as(:command).and_return(assignment)
         | 
| 49 | 
            -
                end
         | 
| 36 | 
            +
                  var_tuple = VarTuple.with_names(%w[aColor aDirection])
         | 
| 37 | 
            +
                  func_call = FunctionCall.new('myFunction', [])
         | 
| 38 | 
            +
                  assignment = MultipleAssignment.new(var_tuple, func_call)
         | 
| 50 39 |  | 
| 40 | 
            +
                  expect('(aColor, aDirection) := myFunction()').to be_parsed_as(:command).and_return(assignment)
         | 
| 41 | 
            +
                end
         | 
| 51 42 | 
             
              end
         | 
| 52 | 
            -
             | 
| 53 43 | 
             
            end
         | 
| @@ -1,111 +1,103 @@ | |
| 1 | 
            -
            describe  | 
| 2 | 
            -
             | 
| 1 | 
            +
            RSpec.describe 'parsing boolean expressions' do
         | 
| 3 2 | 
             
              let(:a) { 'a'.to_var_name }
         | 
| 4 3 | 
             
              let(:b) { 'b'.to_var_name }
         | 
| 5 4 | 
             
              let(:c) { 'c'.to_var_name }
         | 
| 6 5 | 
             
              let(:d) { 'd'.to_var_name }
         | 
| 7 6 |  | 
| 8 | 
            -
              describe  | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
                  eq = Equal.new a, b
         | 
| 7 | 
            +
              describe 'relational operators' do
         | 
| 8 | 
            +
                it 'parses an expression with ==' do
         | 
| 9 | 
            +
                  eq = Equal.new(a, b)
         | 
| 12 10 |  | 
| 13 11 | 
             
                  expect('a==b').to be_parsed_as(:expression).and_return(eq)
         | 
| 14 12 | 
             
                  expect('a  == b').to be_parsed_as(:expression).and_return(eq)
         | 
| 15 13 | 
             
                end
         | 
| 16 14 |  | 
| 17 | 
            -
                it  | 
| 18 | 
            -
                  not_eq = NotEqual.new | 
| 15 | 
            +
                it 'parses an expression with /=' do
         | 
| 16 | 
            +
                  not_eq = NotEqual.new(a, b)
         | 
| 19 17 |  | 
| 20 18 | 
             
                  expect('a/=b').to be_parsed_as(:expression).and_return(not_eq)
         | 
| 21 19 | 
             
                  expect('a /=   b').to be_parsed_as(:expression).and_return(not_eq)
         | 
| 22 20 | 
             
                end
         | 
| 23 21 |  | 
| 24 | 
            -
                it  | 
| 25 | 
            -
                  lt = LessThan.new | 
| 22 | 
            +
                it 'parses an expression with <' do
         | 
| 23 | 
            +
                  lt = LessThan.new(a, b)
         | 
| 26 24 |  | 
| 27 25 | 
             
                  expect('a<b').to be_parsed_as(:expression).and_return(lt)
         | 
| 28 26 | 
             
                  expect('a  <  b').to be_parsed_as(:expression).and_return(lt)
         | 
| 29 27 | 
             
                end
         | 
| 30 28 |  | 
| 31 | 
            -
                it  | 
| 32 | 
            -
                  le = LessEqual.new | 
| 29 | 
            +
                it 'parses an expression with <=' do
         | 
| 30 | 
            +
                  le = LessEqual.new(a, b)
         | 
| 33 31 |  | 
| 34 32 | 
             
                  expect('a<=b').to be_parsed_as(:expression).and_return(le)
         | 
| 35 33 | 
             
                  expect('a  <= b').to be_parsed_as(:expression).and_return(le)
         | 
| 36 34 | 
             
                end
         | 
| 37 35 |  | 
| 38 | 
            -
                it  | 
| 39 | 
            -
                  ge = GreaterEqual.new | 
| 36 | 
            +
                it 'parses an expression with >=' do
         | 
| 37 | 
            +
                  ge = GreaterEqual.new(a, b)
         | 
| 40 38 |  | 
| 41 39 | 
             
                  expect('a>=b').to be_parsed_as(:expression).and_return(ge)
         | 
| 42 40 | 
             
                  expect('a >=  b').to be_parsed_as(:expression).and_return(ge)
         | 
| 43 41 | 
             
                end
         | 
| 44 42 |  | 
| 45 | 
            -
                it  | 
| 46 | 
            -
                  gt = GreaterThan.new | 
| 43 | 
            +
                it 'parses an expression with >' do
         | 
| 44 | 
            +
                  gt = GreaterThan.new(a, b)
         | 
| 47 45 |  | 
| 48 46 | 
             
                  expect('a>b').to be_parsed_as(:expression).and_return(gt)
         | 
| 49 47 | 
             
                  expect('a  > b').to be_parsed_as(:expression).and_return(gt)
         | 
| 50 48 | 
             
                end
         | 
| 51 | 
            -
             | 
| 52 49 | 
             
              end
         | 
| 53 50 |  | 
| 54 | 
            -
              describe  | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
                   | 
| 58 | 
            -
                  not_exp = Not.new exp
         | 
| 51 | 
            +
              describe 'not, and, or' do
         | 
| 52 | 
            +
                it 'parses a not expression' do
         | 
| 53 | 
            +
                  exp = Equal.new(a, b)
         | 
| 54 | 
            +
                  not_exp = Not.new(exp)
         | 
| 59 55 |  | 
| 60 56 | 
             
                  expect('not a == b').to be_parsed_as(:expression).and_return(not_exp)
         | 
| 61 57 | 
             
                end
         | 
| 62 58 |  | 
| 63 | 
            -
                it  | 
| 64 | 
            -
                  exp = And.new | 
| 59 | 
            +
                it 'parses an And expression' do
         | 
| 60 | 
            +
                  exp = And.new(a, b)
         | 
| 65 61 |  | 
| 66 62 | 
             
                  expect('a&&b').to be_parsed_as(:expression).and_return(exp)
         | 
| 67 63 | 
             
                  expect('a &&  b').to be_parsed_as(:expression).and_return(exp)
         | 
| 68 64 | 
             
                end
         | 
| 69 65 |  | 
| 70 | 
            -
                it  | 
| 71 | 
            -
                  exp = Or.new | 
| 66 | 
            +
                it 'parses an Or expression' do
         | 
| 67 | 
            +
                  exp = Or.new(a, b)
         | 
| 72 68 |  | 
| 73 69 | 
             
                  expect('a||b').to be_parsed_as(:expression).and_return(exp)
         | 
| 74 70 | 
             
                  expect('a   || b').to be_parsed_as(:expression).and_return(exp)
         | 
| 75 71 | 
             
                end
         | 
| 76 72 |  | 
| 77 | 
            -
                describe  | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
                     | 
| 81 | 
            -
                    outer_or = Or.new a, inner_or
         | 
| 73 | 
            +
                describe 'nested' do
         | 
| 74 | 
            +
                  it 'parses a nested || expression, associating right' do
         | 
| 75 | 
            +
                    inner_or = Or.new(b, c)
         | 
| 76 | 
            +
                    outer_or = Or.new(a, inner_or)
         | 
| 82 77 |  | 
| 83 78 | 
             
                    expect('a || b || c').to be_parsed_as(:expression).and_return(outer_or)
         | 
| 84 79 | 
             
                  end
         | 
| 85 80 |  | 
| 86 | 
            -
                  it  | 
| 87 | 
            -
                    inner_and = And.new | 
| 88 | 
            -
                    outer_and = And.new | 
| 81 | 
            +
                  it 'parses a nested && expression, associating right' do
         | 
| 82 | 
            +
                    inner_and = And.new(b, c)
         | 
| 83 | 
            +
                    outer_and = And.new(a, inner_and)
         | 
| 89 84 |  | 
| 90 85 | 
             
                    expect('a && b && c').to be_parsed_as(:expression).and_return(outer_and)
         | 
| 91 86 | 
             
                  end
         | 
| 92 87 |  | 
| 93 | 
            -
                  it  | 
| 94 | 
            -
                    bc_and = And.new | 
| 95 | 
            -
                    abc_or = Or.new | 
| 88 | 
            +
                  it 'parses with || taking precedence over &&, left' do
         | 
| 89 | 
            +
                    bc_and = And.new(b, c)
         | 
| 90 | 
            +
                    abc_or = Or.new(a, bc_and)
         | 
| 96 91 |  | 
| 97 92 | 
             
                    expect('a || b && c').to be_parsed_as(:expression).and_return(abc_or)
         | 
| 98 93 | 
             
                  end
         | 
| 99 94 |  | 
| 100 | 
            -
                  it  | 
| 101 | 
            -
                    ab_and = And.new | 
| 102 | 
            -
                    abc_or = Or.new | 
| 95 | 
            +
                  it 'parses with || taking precedence over &&, right' do
         | 
| 96 | 
            +
                    ab_and = And.new(a, b)
         | 
| 97 | 
            +
                    abc_or = Or.new(ab_and, c)
         | 
| 103 98 |  | 
| 104 99 | 
             
                    expect('a && b || c').to be_parsed_as(:expression).and_return(abc_or)
         | 
| 105 100 | 
             
                  end
         | 
| 106 | 
            -
             | 
| 107 101 | 
             
                end
         | 
| 108 | 
            -
             | 
| 109 102 | 
             
              end
         | 
| 110 | 
            -
             | 
| 111 103 | 
             
            end
         | 
| @@ -1,20 +1,19 @@ | |
| 1 | 
            -
            describe Gobstones::Parser,  | 
| 2 | 
            -
             | 
| 3 | 
            -
              it "parses an empty block" do
         | 
| 1 | 
            +
            RSpec.describe Gobstones::Parser, 'command blocks' do
         | 
| 2 | 
            +
              it 'parses an empty block' do
         | 
| 4 3 | 
             
                expect('{}').to be_parsed_as(:command).and_return(CommandBlock.empty)
         | 
| 5 4 | 
             
                expect('{     }').to be_parsed_as(:command).and_return(CommandBlock.empty)
         | 
| 6 5 | 
             
              end
         | 
| 7 6 |  | 
| 8 | 
            -
              it  | 
| 9 | 
            -
                cmd_block = CommandBlock. | 
| 7 | 
            +
              it 'parses a block with one simple cmd' do
         | 
| 8 | 
            +
                cmd_block = CommandBlock.with_just(Skip.new)
         | 
| 10 9 | 
             
                expect('{ Skip }').to be_parsed_as(:command).and_return(cmd_block)
         | 
| 11 10 | 
             
              end
         | 
| 12 11 |  | 
| 13 | 
            -
              it  | 
| 14 | 
            -
                first = Poner.new | 
| 15 | 
            -
                second = Boom.new | 
| 16 | 
            -
                third = Mover.new | 
| 17 | 
            -
                cmd_block = CommandBlock.new | 
| 12 | 
            +
              it 'parses a block with many simple commands' do
         | 
| 13 | 
            +
                first = Poner.new(verde)
         | 
| 14 | 
            +
                second = Boom.new('error')
         | 
| 15 | 
            +
                third = Mover.new(oeste)
         | 
| 16 | 
            +
                cmd_block = CommandBlock.new([first, second, third])
         | 
| 18 17 |  | 
| 19 18 | 
             
                expect('{
         | 
| 20 19 | 
             
                  Poner(Verde)
         | 
| @@ -23,26 +22,25 @@ describe Gobstones::Parser, "command blocks" do | |
| 23 22 | 
             
                 }').to be_parsed_as(:command).and_return(cmd_block)
         | 
| 24 23 | 
             
              end
         | 
| 25 24 |  | 
| 26 | 
            -
              it  | 
| 27 | 
            -
                first = Poner.new | 
| 28 | 
            -
                second = Boom.new | 
| 29 | 
            -
                third = Mover.new | 
| 30 | 
            -
                cmd_block = CommandBlock.new | 
| 25 | 
            +
              it 'allows semicolon between commands' do
         | 
| 26 | 
            +
                first = Poner.new(verde)
         | 
| 27 | 
            +
                second = Boom.new('error')
         | 
| 28 | 
            +
                third = Mover.new(oeste)
         | 
| 29 | 
            +
                cmd_block = CommandBlock.new([first, second, third])
         | 
| 31 30 |  | 
| 32 31 | 
             
                expect('{Poner(Verde); BOOM("error");
         | 
| 33 32 | 
             
                  Mover(Oeste);
         | 
| 34 33 | 
             
                 }').to be_parsed_as(:command).and_return(cmd_block)
         | 
| 35 34 | 
             
              end
         | 
| 36 35 |  | 
| 37 | 
            -
              it  | 
| 38 | 
            -
                first = ProcedureCall.new | 
| 39 | 
            -
                second =  | 
| 40 | 
            -
                cmd_block = CommandBlock.new | 
| 36 | 
            +
              it 'parses a block with simple and complex commands' do
         | 
| 37 | 
            +
                first = ProcedureCall.new('Proc', [])
         | 
| 38 | 
            +
                second = If.new(true_value, empty_body)
         | 
| 39 | 
            +
                cmd_block = CommandBlock.new([first, second])
         | 
| 41 40 |  | 
| 42 41 | 
             
                expect('{
         | 
| 43 42 | 
             
                  Proc()
         | 
| 44 43 | 
             
                  if (True) {}
         | 
| 45 44 | 
             
                 }').to be_parsed_as(:command).and_return(cmd_block)
         | 
| 46 45 | 
             
              end
         | 
| 47 | 
            -
             | 
| 48 46 | 
             
            end
         | 
| @@ -1,31 +1,25 @@ | |
| 1 | 
            -
            describe Gobstones::Parser,  | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
                it "parses a positive number" do
         | 
| 1 | 
            +
            RSpec.describe Gobstones::Parser, 'data types' do
         | 
| 2 | 
            +
              describe 'numbers' do
         | 
| 3 | 
            +
                it 'parses a positive number' do
         | 
| 6 4 | 
             
                  expect('42').to be_parsed_as(:expression).and_return(42.to_gbs_num)
         | 
| 7 5 | 
             
                end
         | 
| 8 6 |  | 
| 9 | 
            -
                it  | 
| 7 | 
            +
                it 'parses a negative number' do
         | 
| 10 8 | 
             
                  expect('-42').to be_parsed_as(:expression).and_return(-42.to_gbs_num)
         | 
| 11 9 | 
             
                end
         | 
| 12 | 
            -
             | 
| 13 10 | 
             
              end
         | 
| 14 11 |  | 
| 15 | 
            -
              describe  | 
| 16 | 
            -
             | 
| 17 | 
            -
                it "parses a true boolean" do
         | 
| 12 | 
            +
              describe 'booleans' do
         | 
| 13 | 
            +
                it 'parses a true boolean' do
         | 
| 18 14 | 
             
                  expect('True').to be_parsed_as(:expression).and_return(true_value)
         | 
| 19 15 | 
             
                end
         | 
| 20 16 |  | 
| 21 | 
            -
                it  | 
| 17 | 
            +
                it 'parses a false boolean' do
         | 
| 22 18 | 
             
                  expect('False').to be_parsed_as(:expression).and_return(false_value)
         | 
| 23 19 | 
             
                end
         | 
| 24 | 
            -
             | 
| 25 20 | 
             
              end
         | 
| 26 21 |  | 
| 27 | 
            -
              describe  | 
| 28 | 
            -
             | 
| 22 | 
            +
              describe 'colors' do
         | 
| 29 23 | 
             
                it "parses the 'Azul' color" do
         | 
| 30 24 | 
             
                  expect('Azul').to be_parsed_as(:expression).and_return(azul)
         | 
| 31 25 | 
             
                end
         | 
| @@ -41,11 +35,9 @@ describe Gobstones::Parser, "data types" do | |
| 41 35 | 
             
                it "parses the 'Verde' color" do
         | 
| 42 36 | 
             
                  expect('Verde').to be_parsed_as(:expression).and_return(verde)
         | 
| 43 37 | 
             
                end
         | 
| 44 | 
            -
             | 
| 45 38 | 
             
              end
         | 
| 46 39 |  | 
| 47 | 
            -
              describe  | 
| 48 | 
            -
             | 
| 40 | 
            +
              describe 'directions' do
         | 
| 49 41 | 
             
                it "parses the 'Norte' direction" do
         | 
| 50 42 | 
             
                  expect('Norte').to be_parsed_as(:expression).and_return(norte)
         | 
| 51 43 | 
             
                end
         | 
| @@ -61,7 +53,5 @@ describe Gobstones::Parser, "data types" do | |
| 61 53 | 
             
                it "parses the 'Oeste' direction" do
         | 
| 62 54 | 
             
                  expect('Oeste').to be_parsed_as(:expression).and_return(oeste)
         | 
| 63 55 | 
             
                end
         | 
| 64 | 
            -
             | 
| 65 56 | 
             
              end
         | 
| 66 | 
            -
             | 
| 67 57 | 
             
            end
         | 
| @@ -1,38 +1,38 @@ | |
| 1 | 
            -
            describe Gobstones::Parser,  | 
| 1 | 
            +
            RSpec.describe Gobstones::Parser, 'function calls' do
         | 
| 2 | 
            +
              it 'parses a function call without args' do
         | 
| 3 | 
            +
                expected = FunctionCall.new('f1')
         | 
| 2 4 |  | 
| 3 | 
            -
              it "parses a function call without args" do
         | 
| 4 | 
            -
                expected = FunctionCall.new 'f1'
         | 
| 5 5 | 
             
                expect('f1()').to be_parsed_as(:expression).and_return(expected)
         | 
| 6 6 | 
             
              end
         | 
| 7 7 |  | 
| 8 | 
            -
              it  | 
| 8 | 
            +
              it 'does not parse a function call without a valid identifier' do
         | 
| 9 9 | 
             
                expect('F1()').to be_parsed_as(:expression).and_fail
         | 
| 10 10 | 
             
              end
         | 
| 11 11 |  | 
| 12 | 
            -
              it  | 
| 13 | 
            -
                expected = FunctionCall.new | 
| 12 | 
            +
              it 'parses a function call with one arg' do
         | 
| 13 | 
            +
                expected = FunctionCall.new('func1', [verde])
         | 
| 14 | 
            +
             | 
| 14 15 | 
             
                expect('func1(Verde)').to be_parsed_as(:expression).and_return(expected)
         | 
| 15 16 | 
             
              end
         | 
| 16 17 |  | 
| 17 | 
            -
              it  | 
| 18 | 
            +
              it 'parses a function with many args' do
         | 
| 18 19 | 
             
                first_arg = 42.to_gbs_num
         | 
| 19 | 
            -
                second_arg = NroBolitas.new | 
| 20 | 
            +
                second_arg = NroBolitas.new(verde)
         | 
| 20 21 | 
             
                third_arg = norte
         | 
| 21 | 
            -
                expected = FunctionCall.new | 
| 22 | 
            +
                expected = FunctionCall.new('func1', [first_arg, second_arg, third_arg])
         | 
| 22 23 |  | 
| 23 | 
            -
                expect('func1(42, nroBolitas(Verde), Norte)').
         | 
| 24 | 
            -
                  to be_parsed_as(:expression).and_return(expected)
         | 
| 24 | 
            +
                expect('func1(42, nroBolitas(Verde), Norte)').to be_parsed_as(:expression).and_return(expected)
         | 
| 25 25 | 
             
              end
         | 
| 26 26 |  | 
| 27 | 
            -
              it  | 
| 28 | 
            -
                or_expr = Or.new | 
| 29 | 
            -
                div = Div.new | 
| 30 | 
            -
                paren_expr = EnclosedByParensExpression.new | 
| 31 | 
            -
                num_expr = Mul.new | 
| 32 | 
            -
                func2_call = FunctionCall.new | 
| 33 | 
            -
                func1_call = FunctionCall.new | 
| 27 | 
            +
              it 'parses a complex function call' do
         | 
| 28 | 
            +
                or_expr = Or.new('a'.to_var_name, 'b'.to_var_name)
         | 
| 29 | 
            +
                div = Div.new(10.to_gbs_num, 'c'.to_var_name)
         | 
| 30 | 
            +
                paren_expr = EnclosedByParensExpression.new(div)
         | 
| 31 | 
            +
                num_expr = Mul.new(5.to_gbs_num, paren_expr)
         | 
| 32 | 
            +
                func2_call = FunctionCall.new('func2', [verde, Opuesto.new(norte)])
         | 
| 33 | 
            +
                func1_call = FunctionCall.new('func1', [or_expr, num_expr, func2_call])
         | 
| 34 | 
            +
             | 
| 34 35 | 
             
                expect('func1(a || b, 5*(10 div c), func2(Verde, opuesto(Norte)))').
         | 
| 35 36 | 
             
                  to be_parsed_as(:expression).and_return(func1_call)
         | 
| 36 37 | 
             
              end
         | 
| 37 | 
            -
             | 
| 38 38 | 
             
            end
         | 
| @@ -1,29 +1,27 @@ | |
| 1 | 
            -
            describe Gobstones::Parser,  | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
                 | 
| 5 | 
            -
             | 
| 6 | 
            -
                func_def = Function.new 'just42', no_arguments, empty_body, func_return
         | 
| 1 | 
            +
            RSpec.describe Gobstones::Parser, 'function definitions' do
         | 
| 2 | 
            +
              it 'parses a function without args and a single return' do
         | 
| 3 | 
            +
                func_return = ReturnFromFunction.new([42.to_gbs_num])
         | 
| 4 | 
            +
                func_def = Function.new('just42', no_arguments, empty_body, func_return)
         | 
| 7 5 |  | 
| 8 6 | 
             
                expect('function just42() { return (42) }').
         | 
| 9 7 | 
             
                  to be_parsed_as(:definition).and_return(func_def)
         | 
| 10 8 | 
             
              end
         | 
| 11 9 |  | 
| 12 | 
            -
              it  | 
| 13 | 
            -
                args = VarTuple. | 
| 14 | 
            -
                return_st = ReturnFromFunction.new | 
| 15 | 
            -
                func_def = Function.new | 
| 10 | 
            +
              it 'parses a function with some args' do
         | 
| 11 | 
            +
                args = VarTuple.with_names(%w[firstArg secondArg thirdArg])
         | 
| 12 | 
            +
                return_st = ReturnFromFunction.new([verde, PuedeMover.new(norte)])
         | 
| 13 | 
            +
                func_def = Function.new('myCoolFunction', args, empty_body, return_st)
         | 
| 16 14 |  | 
| 17 15 | 
             
                expect('function myCoolFunction (firstArg, secondArg, thirdArg) {
         | 
| 18 16 | 
             
              return (Verde, puedeMover(Norte))
         | 
| 19 17 | 
             
            }').to be_parsed_as(:definition).and_return(func_def)
         | 
| 20 18 | 
             
              end
         | 
| 21 19 |  | 
| 22 | 
            -
              it  | 
| 23 | 
            -
                args = VarTuple. | 
| 24 | 
            -
                body = CommandBlock. | 
| 25 | 
            -
                return_st = ReturnFromFunction.new | 
| 26 | 
            -
                func_def = Function.new | 
| 20 | 
            +
              it 'parses a function with some statements' do
         | 
| 21 | 
            +
                args = VarTuple.with_names(%w[arg])
         | 
| 22 | 
            +
                body = CommandBlock.with_just(Poner.new(verde))
         | 
| 23 | 
            +
                return_st = ReturnFromFunction.new([true_value])
         | 
| 24 | 
            +
                func_def = Function.new('myFunc', args, body, return_st)
         | 
| 27 25 |  | 
| 28 26 | 
             
                expect('function myFunc(arg)
         | 
| 29 27 | 
             
            {
         | 
| @@ -32,14 +30,11 @@ describe Gobstones::Parser, "function definitions" do | |
| 32 30 | 
             
            }').to be_parsed_as(:definition).and_return(func_def)
         | 
| 33 31 | 
             
              end
         | 
| 34 32 |  | 
| 35 | 
            -
              it  | 
| 36 | 
            -
                expect('function MyWrongFunc() { return(True) }').
         | 
| 37 | 
            -
                  to be_parsed_as(:definition).and_fail
         | 
| 33 | 
            +
              it 'does not parse a function without a valid identifier' do
         | 
| 34 | 
            +
                expect('function MyWrongFunc() { return(True) }').to be_parsed_as(:definition).and_fail
         | 
| 38 35 | 
             
              end
         | 
| 39 36 |  | 
| 40 | 
            -
              it  | 
| 41 | 
            -
                expect('function myFuncWithoutReturn() { }').
         | 
| 42 | 
            -
                  to be_parsed_as(:definition).and_fail
         | 
| 37 | 
            +
              it 'does not parse a function without a return statement' do
         | 
| 38 | 
            +
                expect('function myFuncWithoutReturn() { }').to be_parsed_as(:definition).and_fail
         | 
| 43 39 | 
             
              end
         | 
| 44 | 
            -
             | 
| 45 40 | 
             
            end
         |