loxxy 0.0.16 → 0.0.17
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 +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +16 -1
- data/README.md +9 -12
- data/lib/loxxy/ast/all_lox_nodes.rb +3 -1
- data/lib/loxxy/ast/ast_builder.rb +12 -1
- data/lib/loxxy/ast/ast_visitor.rb +10 -2
- data/lib/loxxy/ast/lox_binary_expr.rb +1 -1
- data/lib/loxxy/ast/lox_unary_expr.rb +27 -0
- data/lib/loxxy/back_end/engine.rb +13 -3
- data/lib/loxxy/datatype/builtin_datatype.rb +28 -0
- data/lib/loxxy/datatype/false.rb +14 -8
- data/lib/loxxy/datatype/lx_string.rb +0 -14
- data/lib/loxxy/datatype/nil.rb +12 -6
- data/lib/loxxy/datatype/number.rb +44 -6
- data/lib/loxxy/datatype/true.rb +1 -9
- data/lib/loxxy/front_end/grammar.rb +1 -1
- data/lib/loxxy/version.rb +1 -1
- data/spec/interpreter_spec.rb +57 -0
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 6eed6a7de54b89c276b0f098cd7d824f26c0ce9ba957d4fb9e3a4d12e6dfbc4f
         | 
| 4 | 
            +
              data.tar.gz: ba7c00f11c5b69322aec0d447c2fef9cf6d6d74b2ea7bb16096581508a786427
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 1b2c3826f085ce3f723cdbc70c3bdc3563817270985a321db05f97ca1ff81971bf872db49631d3fa20580932f7a0e2910bf3c6c84daf7873cdcd1f04c3392a99
         | 
| 7 | 
            +
              data.tar.gz: 4e3d075facaf9c370d78f3f3ac89b7226e375eb32064535e3401c5ef52b8ca43c9d4c6cfb8f027b4037c7baa7c5945b0fd0dbe1e8b1e580fc732c4a38f7c57c6
         | 
    
        data/.rubocop.yml
    CHANGED
    
    
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,18 @@ | |
| 1 | 
            +
            ## [0.0.17] - 2021-01-12
         | 
| 2 | 
            +
            - The interpreter can evaluate all arithmetic and comparison operations.
         | 
| 3 | 
            +
            - It implements `==`, `!=` and the unary operations `!`, `-`
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ## Added
         | 
| 6 | 
            +
            - Class `AST::LoxUnaryExpr`
         | 
| 7 | 
            +
            - Method `AST::ASTBuilder#reduce_unary_expr` to support the evaluation of `!` and ``-@`
         | 
| 8 | 
            +
            - Method `Ast::ASTVisitor#visit_unnary_expr` for visiting unary expressions
         | 
| 9 | 
            +
            - Method `Backend::Engine#after_unary_expr` evaluating an unary expression
         | 
| 10 | 
            +
            - In class `Datatype::BuiltinDatatype` the methods `falsey?`, `truthy?`, `!`, `!=`
         | 
| 11 | 
            +
            - In class `Datatype::Number`the methods `<`, `<=`, ´>´, `>=` and `-@`
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            ## Changed
         | 
| 14 | 
            +
            - File `README.md` updated.
         | 
| 15 | 
            +
             | 
| 1 16 | 
             
            ## [0.0.16] - 2021-01-11
         | 
| 2 17 | 
             
            - The interpreter can evaluate product and division of two numbers.
         | 
| 3 18 | 
             
            - It also implements equality `==` and inequality `!=` operators
         | 
| @@ -36,7 +51,7 @@ | |
| 36 51 | 
             
            - The interpreter can evaluate addition of numbers and string concatenation
         | 
| 37 52 |  | 
| 38 53 | 
             
            ## Added
         | 
| 39 | 
            -
            - Method `Ast::ASTVisitor | 
| 54 | 
            +
            - Method `Ast::ASTVisitor#visit_binary_expr` for visiting binary expressions
         | 
| 40 55 | 
             
            - Method `Ast::LoxBinaryExpr#accept` for visitor pattern
         | 
| 41 56 | 
             
            - Method `BackEnd::Engine#after_binary_expr` to trigger execution of binary operator
         | 
| 42 57 | 
             
            - `Boolean` class hierarchy: added methos `true?` and `false?` to ease spec test writing
         | 
    
        data/README.md
    CHANGED
    
    | @@ -154,21 +154,16 @@ The parser knows all the __Lox__ reserved keywords: | |
| 154 154 | 
             
            and, class, else, false, fun, for, if, nil, or,
         | 
| 155 155 | 
             
            print, return, super, this, true, var, while
         | 
| 156 156 | 
             
            ```
         | 
| 157 | 
            -
            Of these, the interpreter implements: `false`, `nil`, `true`
         | 
| 157 | 
            +
            Of these, the interpreter implements: `false`, `nil`, `print`, `true`
         | 
| 158 158 |  | 
| 159 159 | 
             
            ### Operators and Special Chars
         | 
| 160 160 | 
             
            #### Operators
         | 
| 161 | 
            -
            The  | 
| 161 | 
            +
            The __loxxy__ interpreter supports all the __Lox__ unary and binary operators:
         | 
| 162 162 | 
             
            - Arithmetic operators: `+`, `-`, `*`, `/`
         | 
| 163 163 | 
             
            - Comparison operators: `>`, `>=`, `<`, `<=`
         | 
| 164 164 | 
             
            - Equality operators: `==`, `!=`
         | 
| 165 | 
            -
             | 
| 166 | 
            -
             | 
| 167 | 
            -
            `+` (addition of two numbers or string concatenation)
         | 
| 168 | 
            -
            `-` (difference between two numbers)
         | 
| 169 | 
            -
            `*` (product of two numbers)
         | 
| 170 | 
            -
            `/` (division of two number)
         | 
| 171 | 
            -
            `==` and `!=` (in)equality testing of two Lox values
         | 
| 165 | 
            +
            - Unary negate (change sign): `-`
         | 
| 166 | 
            +
            - Unary not: `!`
         | 
| 172 167 |  | 
| 173 168 | 
             
            #### Delimiters
         | 
| 174 169 | 
             
            The parser knows all the __Lox__ grouping delimiters:  
         | 
| @@ -196,9 +191,11 @@ loxxy supports  all the standard __Lox__ datatypes: | |
| 196 191 | 
             
            ### Implemented expressions
         | 
| 197 192 | 
             
            Loxxy implements expressions:
         | 
| 198 193 | 
             
            - Plain literals only; or,
         | 
| 199 | 
            -
            -  | 
| 194 | 
            +
            - (In)equality testing between two values; or,   
         | 
| 195 | 
            +
            - Basic arithmetic operations (`+`, `-`, `*`, `/`, `unary -`); or,  
         | 
| 196 | 
            +
            - Comparison between two numbers; or,
         | 
| 200 197 | 
             
            - Concatenation of two strings,
         | 
| 201 | 
            -
            -  | 
| 198 | 
            +
            - Negation `!`
         | 
| 202 199 |  | 
| 203 200 | 
             
            ### Implemented statements
         | 
| 204 201 | 
             
            Loxxy implements the following statements:
         | 
| @@ -206,7 +203,7 @@ Loxxy implements the following statements: | |
| 206 203 | 
             
            - Print statement
         | 
| 207 204 |  | 
| 208 205 | 
             
            ```javascript
         | 
| 209 | 
            -
            // Print statement with nested concatenation
         | 
| 206 | 
            +
            // Print statement with nested string concatenation
         | 
| 210 207 | 
             
            print "Hello" + ", " + "world!";
         | 
| 211 208 | 
             
            ```
         | 
| 212 209 |  | 
| @@ -15,7 +15,6 @@ module Loxxy | |
| 15 15 | 
             
                    # @return [Hash{String => String}]
         | 
| 16 16 | 
             
                    Name2special = {
         | 
| 17 17 | 
             
                      'AND' => 'and',
         | 
| 18 | 
            -
                      'BANG' => '!',
         | 
| 19 18 | 
             
                      'BANG_EQUAL' => '!=',
         | 
| 20 19 | 
             
                      'COMMA' =>  ',',
         | 
| 21 20 | 
             
                      'DOT' => '.',
         | 
| @@ -36,6 +35,11 @@ module Loxxy | |
| 36 35 | 
             
                      'SLASH' =>  '/',
         | 
| 37 36 | 
             
                      'STAR' => '*'
         | 
| 38 37 | 
             
                    }.freeze
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    Name2unary = {
         | 
| 40 | 
            +
                      'BANG' => '!',
         | 
| 41 | 
            +
                      'MINUS' => '-@'
         | 
| 42 | 
            +
                    }.freeze
         | 
| 39 43 | 
             
                  end # defined
         | 
| 40 44 |  | 
| 41 45 | 
             
                  attr_reader :strict
         | 
| @@ -231,6 +235,13 @@ module Loxxy | |
| 231 235 | 
             
                    reduce_binary_plus_end(production, range, tokens, theChildren)
         | 
| 232 236 | 
             
                  end
         | 
| 233 237 |  | 
| 238 | 
            +
                  # rule('unary' => 'unaryOp unary')
         | 
| 239 | 
            +
                  def reduce_unary_expr(_production, _range, tokens, theChildren)
         | 
| 240 | 
            +
                    operator = Name2unary[theChildren[0].symbol.name].to_sym
         | 
| 241 | 
            +
                    operand = theChildren[1]
         | 
| 242 | 
            +
                    LoxUnaryExpr.new(tokens[0].position, operator, operand)
         | 
| 243 | 
            +
                  end
         | 
| 244 | 
            +
             | 
| 234 245 | 
             
                  # rule('primary' => 'FALSE' | TRUE').as 'literal_expr'
         | 
| 235 246 | 
             
                  def reduce_literal_expr(_production, _range, _tokens, theChildren)
         | 
| 236 247 | 
             
                    first_child = theChildren.first
         | 
| @@ -51,7 +51,7 @@ module Loxxy | |
| 51 51 | 
             
                    broadcast(:after_ptree, aParseTree)
         | 
| 52 52 | 
             
                  end
         | 
| 53 53 |  | 
| 54 | 
            -
                  # Visit event. The visitor is about to visit a print statement | 
| 54 | 
            +
                  # Visit event. The visitor is about to visit a print statement.
         | 
| 55 55 | 
             
                  # @param aPrintStmt [AST::LOXPrintStmt] the print statement node to visit
         | 
| 56 56 | 
             
                  def visit_print_stmt(aPrintStmt)
         | 
| 57 57 | 
             
                    broadcast(:before_print_stmt, aPrintStmt)
         | 
| @@ -59,7 +59,7 @@ module Loxxy | |
| 59 59 | 
             
                    broadcast(:after_print_stmt, aPrintStmt)
         | 
| 60 60 | 
             
                  end
         | 
| 61 61 |  | 
| 62 | 
            -
                  # Visit event. The visitor is about to visit a  | 
| 62 | 
            +
                  # Visit event. The visitor is about to visit a binary expression.
         | 
| 63 63 | 
             
                  # @param aBinaryExpr [AST::LOXBinaryExpr] the binary expression node to visit
         | 
| 64 64 | 
             
                  def visit_binary_expr(aBinaryExpr)
         | 
| 65 65 | 
             
                    broadcast(:before_binary_expr, aBinaryExpr)
         | 
| @@ -67,6 +67,14 @@ module Loxxy | |
| 67 67 | 
             
                    broadcast(:after_binary_expr, aBinaryExpr)
         | 
| 68 68 | 
             
                  end
         | 
| 69 69 |  | 
| 70 | 
            +
                  # Visit event. The visitor is about to visit an unary expression.
         | 
| 71 | 
            +
                  # @param anUnaryExpr [AST::anUnaryExpr] unary expression node to visit
         | 
| 72 | 
            +
                  def visit_unary_expr(anUnaryExpr)
         | 
| 73 | 
            +
                    broadcast(:before_unary_expr, anUnaryExpr)
         | 
| 74 | 
            +
                    traverse_subnodes(anUnaryExpr)
         | 
| 75 | 
            +
                    broadcast(:after_unary_expr, anUnaryExpr)
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
             | 
| 70 78 | 
             
                  # Visit event. The visitor is visiting the
         | 
| 71 79 | 
             
                  # given terminal node containing a datatype object.
         | 
| 72 80 | 
             
                  # @param aLiteralExpr [AST::LoxLiteralExpr] the leaf node to visit.
         | 
| @@ -5,7 +5,7 @@ require_relative 'lox_compound_expr' | |
| 5 5 | 
             
            module Loxxy
         | 
| 6 6 | 
             
              module Ast
         | 
| 7 7 | 
             
                class LoxBinaryExpr < LoxCompoundExpr
         | 
| 8 | 
            -
                  # @return [Symbol]
         | 
| 8 | 
            +
                  # @return [Symbol] message name to be sent to receiver
         | 
| 9 9 | 
             
                  attr_reader :operator
         | 
| 10 10 |  | 
| 11 11 | 
             
                  # @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative 'lox_compound_expr'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Loxxy
         | 
| 6 | 
            +
              module Ast
         | 
| 7 | 
            +
                class LoxUnaryExpr < LoxCompoundExpr
         | 
| 8 | 
            +
                  # @return [Symbol] message name to be sent to receiver
         | 
| 9 | 
            +
                  attr_reader :operator
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  # @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
         | 
| 12 | 
            +
                  # @param operand [Loxxy::Ast::LoxNode]
         | 
| 13 | 
            +
                  def initialize(aPosition, anOperator, operand)
         | 
| 14 | 
            +
                    super(aPosition, [operand])
         | 
| 15 | 
            +
                    @operator = anOperator
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  # Part of the 'visitee' role in Visitor design pattern.
         | 
| 19 | 
            +
                  # @param visitor [Ast::ASTVisitor] the visitor
         | 
| 20 | 
            +
                  def accept(visitor)
         | 
| 21 | 
            +
                    visitor.visit_unary_expr(self)
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  alias operands subnodes
         | 
| 25 | 
            +
                end # class
         | 
| 26 | 
            +
              end # module
         | 
| 27 | 
            +
            end # module
         | 
| @@ -22,7 +22,7 @@ module Loxxy | |
| 22 22 | 
             
                    @stack = []
         | 
| 23 23 | 
             
                  end
         | 
| 24 24 |  | 
| 25 | 
            -
                  # Given an abstract syntax parse tree visitor,  | 
| 25 | 
            +
                  # Given an abstract syntax parse tree visitor, launch the visit
         | 
| 26 26 | 
             
                  # and execute the visit events in the output stream.
         | 
| 27 27 | 
             
                  # @param aVisitor [AST::ASTVisitor]
         | 
| 28 28 | 
             
                  # @return [Loxxy::Datatype::BuiltinDatatype]
         | 
| @@ -44,8 +44,7 @@ module Loxxy | |
| 44 44 | 
             
                    op = aBinaryExpr.operator
         | 
| 45 45 | 
             
                    operand2 = stack.pop
         | 
| 46 46 | 
             
                    operand1 = stack.pop
         | 
| 47 | 
            -
                     | 
| 48 | 
            -
                    if implemented && operand1.respond_to?(op)
         | 
| 47 | 
            +
                    if operand1.respond_to?(op)
         | 
| 49 48 | 
             
                      stack.push operand1.send(op, operand2)
         | 
| 50 49 | 
             
                    else
         | 
| 51 50 | 
             
                      msg1 = "`#{op}': Unimplemented operator for a #{operand1.class}."
         | 
| @@ -53,6 +52,17 @@ module Loxxy | |
| 53 52 | 
             
                    end
         | 
| 54 53 | 
             
                  end
         | 
| 55 54 |  | 
| 55 | 
            +
                  def after_unary_expr(anUnaryExpr)
         | 
| 56 | 
            +
                    op = anUnaryExpr.operator
         | 
| 57 | 
            +
                    operand = stack.pop
         | 
| 58 | 
            +
                    if operand.respond_to?(op)
         | 
| 59 | 
            +
                      stack.push operand.send(op)
         | 
| 60 | 
            +
                    else
         | 
| 61 | 
            +
                      msg1 = "`#{op}': Unimplemented operator for a #{operand1.class}."
         | 
| 62 | 
            +
                      raise StandardError, msg1
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 56 66 | 
             
                  # @param literalExpr [Ast::LoxLiteralExpr]
         | 
| 57 67 | 
             
                  def before_literal_expr(literalExpr)
         | 
| 58 68 | 
             
                    stack.push(literalExpr.literal)
         | 
| @@ -14,6 +14,34 @@ module Loxxy | |
| 14 14 | 
             
                    @value = validated_value(aValue)
         | 
| 15 15 | 
             
                  end
         | 
| 16 16 |  | 
| 17 | 
            +
                  # Is the value considered falsey in Lox?
         | 
| 18 | 
            +
                  # Rule: false and nil are falsey and everything else is truthy.
         | 
| 19 | 
            +
                  # This test used in conditional statements (i.e. if, while)
         | 
| 20 | 
            +
                  def falsey?
         | 
| 21 | 
            +
                    false # Default implementation
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  # Is the value considered truthy in Lox?
         | 
| 25 | 
            +
                  # Rule: false and nil are falsey and everything else is truthy.
         | 
| 26 | 
            +
                  # This test used in conditional statements (i.e. if, while)
         | 
| 27 | 
            +
                  def truthy?
         | 
| 28 | 
            +
                    true # Default implementation
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  # Negation ('not')
         | 
| 32 | 
            +
                  # Returns a boolean with opposite truthiness value.
         | 
| 33 | 
            +
                  # @return [Datatype::Boolean]
         | 
| 34 | 
            +
                  def !
         | 
| 35 | 
            +
                    falsey? ? True.instance : False.instance
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  # Check for inequality of this object with another Lox object
         | 
| 39 | 
            +
                  # @param other [Datatype::BuiltinDatatype, Object]
         | 
| 40 | 
            +
                  # @return [Datatype::Boolean]
         | 
| 41 | 
            +
                  def !=(other)
         | 
| 42 | 
            +
                    !(self == other)
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 17 45 | 
             
                  # Method called from Lox to obtain the text representation of the boolean.
         | 
| 18 46 | 
             
                  # @return [String]
         | 
| 19 47 | 
             
                  def to_str
         | 
    
        data/lib/loxxy/datatype/false.rb
    CHANGED
    
    | @@ -20,6 +20,20 @@ module Loxxy | |
| 20 20 | 
             
                    true
         | 
| 21 21 | 
             
                  end
         | 
| 22 22 |  | 
| 23 | 
            +
                  # Is the value considered falsey in Lox?
         | 
| 24 | 
            +
                  # Rule: false and nil are falsey and everything else is truthy.
         | 
| 25 | 
            +
                  # This test used in conditional statements (i.e. if, while)
         | 
| 26 | 
            +
                  def falsey?
         | 
| 27 | 
            +
                    true
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  # Is the value considered truthy in Lox?
         | 
| 31 | 
            +
                  # Rule: false and nil are falsey and everything else is truthy.
         | 
| 32 | 
            +
                  # This test used in conditional statements (i.e. if, while)
         | 
| 33 | 
            +
                  def truthy?
         | 
| 34 | 
            +
                    false
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 23 37 | 
             
                  # Check for equality of a Lox False with another Lox object
         | 
| 24 38 | 
             
                  # @param other [Datatype::BuiltinDatatype, FalseClass, Object]
         | 
| 25 39 | 
             
                  # @return [Datatype::Boolean]
         | 
| @@ -27,14 +41,6 @@ module Loxxy | |
| 27 41 | 
             
                    falsey = other.kind_of?(False) || other.kind_of?(FalseClass)
         | 
| 28 42 | 
             
                    falsey ? True.instance : False.instance
         | 
| 29 43 | 
             
                  end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                  # Check for inequality of a Lox False with another Lox object
         | 
| 32 | 
            -
                  # @param other [Datatype::BuiltinDatatype, FalseClass, Object]
         | 
| 33 | 
            -
                  # @return [Datatype::Boolean]
         | 
| 34 | 
            -
                  def !=(other)
         | 
| 35 | 
            -
                    falsey = other.kind_of?(False) || other.kind_of?(FalseClass)
         | 
| 36 | 
            -
                    falsey ? False.instance : True.instance
         | 
| 37 | 
            -
                  end
         | 
| 38 44 | 
             
                end # class
         | 
| 39 45 |  | 
| 40 46 | 
             
                False.instance.freeze # Make the sole instance immutable
         | 
| @@ -21,20 +21,6 @@ module Loxxy | |
| 21 21 | 
             
                    end
         | 
| 22 22 | 
             
                  end
         | 
| 23 23 |  | 
| 24 | 
            -
                  # Check the inequality of a Lox String with another Lox object.
         | 
| 25 | 
            -
                  # @param other [Datatype::LxString, String, Object]
         | 
| 26 | 
            -
                  # @return [Datatype::Boolean]
         | 
| 27 | 
            -
                  def !=(other)
         | 
| 28 | 
            -
                    case other
         | 
| 29 | 
            -
                    when LXString
         | 
| 30 | 
            -
                      (value != other.value) ? True.instance : False.instance
         | 
| 31 | 
            -
                    when String
         | 
| 32 | 
            -
                      (value != other) ? True.instance : False.instance
         | 
| 33 | 
            -
                    else
         | 
| 34 | 
            -
                      True.instance
         | 
| 35 | 
            -
                    end
         | 
| 36 | 
            -
                  end
         | 
| 37 | 
            -
             | 
| 38 24 | 
             
                  # Perform the concatenation of two Lox stings or
         | 
| 39 25 | 
             
                  # one Lox string and a Ruby String
         | 
| 40 26 | 
             
                  # @param other [Loxxy::Datatype::LXString, String]
         | 
    
        data/lib/loxxy/datatype/nil.rb
    CHANGED
    
    | @@ -22,12 +22,18 @@ module Loxxy | |
| 22 22 | 
             
                    is_nil ? True.instance : False.instance
         | 
| 23 23 | 
             
                  end
         | 
| 24 24 |  | 
| 25 | 
            -
                  #  | 
| 26 | 
            -
                  #  | 
| 27 | 
            -
                  #  | 
| 28 | 
            -
                  def  | 
| 29 | 
            -
                     | 
| 30 | 
            -
             | 
| 25 | 
            +
                  # Is the value considered falsey in Lox?
         | 
| 26 | 
            +
                  # Rule: false and nil are falsey and everything else is truthy.
         | 
| 27 | 
            +
                  # This test used in conditional statements (i.e. if, while)
         | 
| 28 | 
            +
                  def falsey?
         | 
| 29 | 
            +
                    true
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  # Is the value considered truthy in Lox?
         | 
| 33 | 
            +
                  # Rule: false and nil are falsey and everything else is truthy.
         | 
| 34 | 
            +
                  # This test used in conditional statements (i.e. if, while)
         | 
| 35 | 
            +
                  def truthy?
         | 
| 36 | 
            +
                    false
         | 
| 31 37 | 
             
                  end
         | 
| 32 38 |  | 
| 33 39 | 
             
                  # Method called from Lox to obtain the text representation of nil.
         | 
| @@ -71,6 +71,12 @@ module Loxxy | |
| 71 71 | 
             
                    end
         | 
| 72 72 | 
             
                  end
         | 
| 73 73 |  | 
| 74 | 
            +
                  # Unary minus (return value with changed sign)
         | 
| 75 | 
            +
                  # @return [Loxxy::Datatype::Number]
         | 
| 76 | 
            +
                  def -@
         | 
| 77 | 
            +
                    self.class.new(-value)
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 74 80 | 
             
                  # Check the equality of a Lox number object with another object
         | 
| 75 81 | 
             
                  # @param other [Datatype::BuiltinDatatype, Numeric, Object]
         | 
| 76 82 | 
             
                  # @return [Datatype::Boolean]
         | 
| @@ -85,20 +91,52 @@ module Loxxy | |
| 85 91 | 
             
                    end
         | 
| 86 92 | 
             
                  end
         | 
| 87 93 |  | 
| 88 | 
            -
                  # Check  | 
| 89 | 
            -
                  # @param other [Datatype:: | 
| 94 | 
            +
                  # Check whether this Lox number has a greater value than given argument.
         | 
| 95 | 
            +
                  # @param other [Datatype::Number, Numeric]
         | 
| 96 | 
            +
                  # @return [Datatype::Boolean]
         | 
| 97 | 
            +
                  def >(other)
         | 
| 98 | 
            +
                    case other
         | 
| 99 | 
            +
                    when Number
         | 
| 100 | 
            +
                      (value > other.value) ? True.instance : False.instance
         | 
| 101 | 
            +
                    when Numeric
         | 
| 102 | 
            +
                      (value > other) ? True.instance : False.instance
         | 
| 103 | 
            +
                    else
         | 
| 104 | 
            +
                      msg = "'>': Operands must be numbers."
         | 
| 105 | 
            +
                      raise StandardError, msg
         | 
| 106 | 
            +
                    end
         | 
| 107 | 
            +
                  end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  # Check whether this Lox number has a greater or equal value
         | 
| 110 | 
            +
                  # than given argument.
         | 
| 111 | 
            +
                  # @param other [Datatype::Number, Numeric]
         | 
| 90 112 | 
             
                  # @return [Datatype::Boolean]
         | 
| 91 | 
            -
                  def  | 
| 113 | 
            +
                  def >=(other)
         | 
| 92 114 | 
             
                    case other
         | 
| 93 115 | 
             
                    when Number
         | 
| 94 | 
            -
                      (value  | 
| 116 | 
            +
                      (value >= other.value) ? True.instance : False.instance
         | 
| 95 117 | 
             
                    when Numeric
         | 
| 96 | 
            -
                      (value  | 
| 118 | 
            +
                      (value >= other) ? True.instance : False.instance
         | 
| 97 119 | 
             
                    else
         | 
| 98 | 
            -
                       | 
| 120 | 
            +
                      msg = "'>': Operands must be numbers."
         | 
| 121 | 
            +
                      raise StandardError, msg
         | 
| 99 122 | 
             
                    end
         | 
| 100 123 | 
             
                  end
         | 
| 101 124 |  | 
| 125 | 
            +
                  # Check whether this Lox number has a lesser value than given argument.
         | 
| 126 | 
            +
                  # @param other [Datatype::Number, Numeric]
         | 
| 127 | 
            +
                  # @return [Datatype::Boolean]
         | 
| 128 | 
            +
                  def <(other)
         | 
| 129 | 
            +
                    !(self >= other)
         | 
| 130 | 
            +
                  end
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                  # Check whether this Lox number has a lesser or equal value
         | 
| 133 | 
            +
                  # than given argument.
         | 
| 134 | 
            +
                  # @param other [Datatype::Number, Numeric]
         | 
| 135 | 
            +
                  # @return [Datatype::Boolean]
         | 
| 136 | 
            +
                  def <=(other)
         | 
| 137 | 
            +
                    !(self > other)
         | 
| 138 | 
            +
                  end
         | 
| 139 | 
            +
             | 
| 102 140 | 
             
                  protected
         | 
| 103 141 |  | 
| 104 142 | 
             
                  def validated_value(aValue)
         | 
    
        data/lib/loxxy/datatype/true.rb
    CHANGED
    
    | @@ -20,21 +20,13 @@ module Loxxy | |
| 20 20 | 
             
                    true
         | 
| 21 21 | 
             
                  end
         | 
| 22 22 |  | 
| 23 | 
            -
                  # Check for equality of a Lox True with another Lox object
         | 
| 23 | 
            +
                  # Check for equality of a Lox True with another Lox object / Ruby true
         | 
| 24 24 | 
             
                  # @param other [Datatype::True, TrueClass, Object]
         | 
| 25 25 | 
             
                  # @return [Datatype::Boolean]
         | 
| 26 26 | 
             
                  def ==(other)
         | 
| 27 27 | 
             
                    thruthy = other.kind_of?(True) || other.kind_of?(TrueClass)
         | 
| 28 28 | 
             
                    thruthy ? True.instance : False.instance
         | 
| 29 29 | 
             
                  end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                  # Check for inequality of a Lox True with another Lox object
         | 
| 32 | 
            -
                  # @param other [Datatype::BuiltinDatatype, TrueClass, Object]
         | 
| 33 | 
            -
                  # @return [Datatype::Boolean]
         | 
| 34 | 
            -
                  def !=(other)
         | 
| 35 | 
            -
                    thruthy = other.kind_of?(True) || other.kind_of?(TrueClass)
         | 
| 36 | 
            -
                    thruthy ? False.instance : True.instance
         | 
| 37 | 
            -
                  end
         | 
| 38 30 | 
             
                end # class
         | 
| 39 31 |  | 
| 40 32 | 
             
                True.instance.freeze # Make the sole instance immutable
         | 
| @@ -121,7 +121,7 @@ module Loxxy | |
| 121 121 | 
             
                  rule('multiplicative_plus' => 'multOp unary').as 'multiplicative_plus_end'
         | 
| 122 122 | 
             
                  rule('multOp' => 'SLASH')
         | 
| 123 123 | 
             
                  rule('multOp' => 'STAR')
         | 
| 124 | 
            -
                  rule('unary' => 'unaryOp unary')
         | 
| 124 | 
            +
                  rule('unary' => 'unaryOp unary').as 'unary_expr'
         | 
| 125 125 | 
             
                  rule('unary' => 'call')
         | 
| 126 126 | 
             
                  rule('unaryOp' => 'BANG')
         | 
| 127 127 | 
             
                  rule('unaryOp' => 'MINUS')
         | 
    
        data/lib/loxxy/version.rb
    CHANGED
    
    
    
        data/spec/interpreter_spec.rb
    CHANGED
    
    | @@ -107,6 +107,63 @@ module Loxxy | |
| 107 107 | 
             
                    end
         | 
| 108 108 | 
             
                  end
         | 
| 109 109 |  | 
| 110 | 
            +
                  it 'should evaluate a comparison of two numbers' do
         | 
| 111 | 
            +
                    [
         | 
| 112 | 
            +
                      ['1 < 2;', true],
         | 
| 113 | 
            +
                      ['2 < 2;', false],
         | 
| 114 | 
            +
                      ['2 < 1;', false],
         | 
| 115 | 
            +
                      ['1 <= 2;', true],
         | 
| 116 | 
            +
                      ['2 <= 2;', true],
         | 
| 117 | 
            +
                      ['2 <= 1;', false],
         | 
| 118 | 
            +
                      ['1 > 2;', false],
         | 
| 119 | 
            +
                      ['2 > 2;', false],
         | 
| 120 | 
            +
                      ['2 > 1;', true],
         | 
| 121 | 
            +
                      ['1 >= 2;', false],
         | 
| 122 | 
            +
                      ['2 >= 2;', true],
         | 
| 123 | 
            +
                      ['2 >= 1;', true],
         | 
| 124 | 
            +
                      ['0 < -0;', false],
         | 
| 125 | 
            +
                      ['-0 < 0;', false],
         | 
| 126 | 
            +
                      ['0 > -0;', false],
         | 
| 127 | 
            +
                      ['-0 > 0;', false],
         | 
| 128 | 
            +
                      ['0 <= -0;', true],
         | 
| 129 | 
            +
                      ['-0 <= 0;', true],
         | 
| 130 | 
            +
                      ['0 >= -0;', true],
         | 
| 131 | 
            +
                      ['-0 >= 0;', true]
         | 
| 132 | 
            +
                    ].each do |(source, predicted)|
         | 
| 133 | 
            +
                      lox = Loxxy::Interpreter.new
         | 
| 134 | 
            +
                      result = lox.evaluate(source)
         | 
| 135 | 
            +
                      expect(result.value == predicted).to be_truthy
         | 
| 136 | 
            +
                    end
         | 
| 137 | 
            +
                  end
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                  it 'should evaluate the change sign of a number' do
         | 
| 140 | 
            +
                    [
         | 
| 141 | 
            +
                      ['- 3;', -3],
         | 
| 142 | 
            +
                      ['- - 3;', 3],
         | 
| 143 | 
            +
                      ['- - - 3;', -3]
         | 
| 144 | 
            +
                    ].each do |(source, predicted)|
         | 
| 145 | 
            +
                      lox = Loxxy::Interpreter.new
         | 
| 146 | 
            +
                      result = lox.evaluate(source)
         | 
| 147 | 
            +
                      expect(result.value == predicted).to be_truthy
         | 
| 148 | 
            +
                    end
         | 
| 149 | 
            +
                  end
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                  it 'should evaluate the negation of an object' do
         | 
| 152 | 
            +
                    [
         | 
| 153 | 
            +
                      ['!true;', false],
         | 
| 154 | 
            +
                      ['!false;', true],
         | 
| 155 | 
            +
                      ['!!true;', true],
         | 
| 156 | 
            +
                      ['!123;', false],
         | 
| 157 | 
            +
                      ['!0;', false],
         | 
| 158 | 
            +
                      ['!nil;', true],
         | 
| 159 | 
            +
                      ['!"";', false]
         | 
| 160 | 
            +
                    ].each do |(source, predicted)|
         | 
| 161 | 
            +
                      lox = Loxxy::Interpreter.new
         | 
| 162 | 
            +
                      result = lox.evaluate(source)
         | 
| 163 | 
            +
                      expect(result.value == predicted).to be_truthy
         | 
| 164 | 
            +
                    end
         | 
| 165 | 
            +
                  end
         | 
| 166 | 
            +
             | 
| 110 167 | 
             
                  it 'should print the hello world message' do
         | 
| 111 168 | 
             
                    expect { subject.evaluate(hello_world) }.not_to raise_error
         | 
| 112 169 | 
             
                    expect(sample_cfg[:ostream].string).to eq('Hello, world!')
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: loxxy
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.17
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Dimitri Geshef
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021-01- | 
| 11 | 
            +
            date: 2021-01-12 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rley
         | 
| @@ -93,6 +93,7 @@ files: | |
| 93 93 | 
             
            - lib/loxxy/ast/lox_node.rb
         | 
| 94 94 | 
             
            - lib/loxxy/ast/lox_noop_expr.rb
         | 
| 95 95 | 
             
            - lib/loxxy/ast/lox_print_stmt.rb
         | 
| 96 | 
            +
            - lib/loxxy/ast/lox_unary_expr.rb
         | 
| 96 97 | 
             
            - lib/loxxy/back_end/engine.rb
         | 
| 97 98 | 
             
            - lib/loxxy/datatype/all_datatypes.rb
         | 
| 98 99 | 
             
            - lib/loxxy/datatype/boolean.rb
         |