loxxy 0.0.15 → 0.0.16

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7624afc97e5e8d3cee171dc9fbbe7a45c45698595109a5281d9f58fcaebd73ec
4
- data.tar.gz: 67ec959b7758245f414314ea9c8b0a2bbf40a5e01133f17325fa40ab720858f0
3
+ metadata.gz: 7d7d30d3246aa8a8f06f3456d3996c680e9ddb4ed31bcf9fff99685702e50dd1
4
+ data.tar.gz: dc428ddd0fc03e153e70873bc2827b6e4aac813e5fdfba40ef2f28bfa7283fc2
5
5
  SHA512:
6
- metadata.gz: adcb9cf6b353b09cf623df330fbdff35255571f8781dfd0b46ea6ab32c02cf55bd0130f94414cd91aa8cb798b1ea7cd4aef4844acc556147b5e4b387d099b8c0
7
- data.tar.gz: 47230281481b965fe1dddd74f763568a0ca125454800984c41fb29629d26c37ae8f7fa0320a38ca784abe605dfb5dc14f4a9c26b0d269240ea07c5e2feb6241b
6
+ metadata.gz: d90f2494a324be036dae2f3d38636c571009b60f19d2b3d917b242ab98d231e03bb121f577e5598ac63514cc5817814972cabe927f05af2842a5a97c89eb69d9
7
+ data.tar.gz: e09a70a27baa1408904e1bfe512f4f523b8e4efd1aab00412b993c8f4a35b5498f1f6ddb5e67697108c80a91778301e41c15741451e73e1d869496d96441757a
@@ -1,3 +1,25 @@
1
+ ## [0.0.16] - 2021-01-11
2
+ - The interpreter can evaluate product and division of two numbers.
3
+ - It also implements equality `==` and inequality `!=` operators
4
+
5
+ ## Added
6
+ - Method `Datatype::False#==` for equality testing
7
+ - Method `Datatype::False#!=` for inequality testing
8
+ - Method `Datatype::LXString#==` for equality testing
9
+ - Method `Datatype::LXString#!=` for inequality testing
10
+ - Method `Datatype::Nil#==` for equality testing
11
+ - Method `Datatype::Nil#!=` for inequality testing
12
+ - Method `Datatype::Number#==` for equality testing
13
+ - Method `Datatype::Number#!=` for inequality testing
14
+ - Method `Datatype::Number#*` for multiply operator
15
+ - Method `Datatype::Number#/` for divide operator
16
+ - Method `Datatype::True#==` for equality testing
17
+ - Method `Datatype::True#!=` for inequality testing
18
+
19
+ ## Changed
20
+ - Method `BackEnd::Engine#after_binary_expr` to allow `*`, `/`, `==`, `!=` operators
21
+ - File `README.md` updated for the newly implemented operators
22
+
1
23
  ## [0.0.15] - 2021-01-11
2
24
  - The interpreter can evaluate substraction between two numbers.
3
25
 
data/README.md CHANGED
@@ -166,6 +166,9 @@ The parser recognizes all the __Lox__ operators, delimiters and separators:
166
166
  Of these, the interpreter implements:
167
167
  `+` (addition of two numbers or string concatenation)
168
168
  `-` (difference between two numbers)
169
+ `*` (product of two numbers)
170
+ `/` (division of two number)
171
+ `==` and `!=` (in)equality testing of two Lox values
169
172
 
170
173
  #### Delimiters
171
174
  The parser knows all the __Lox__ grouping delimiters:
@@ -193,9 +196,9 @@ loxxy supports all the standard __Lox__ datatypes:
193
196
  ### Implemented expressions
194
197
  Loxxy implements expressions:
195
198
  - Plain literals only; or,
196
- - Addition of two numbers; or,
197
- - Subtraction of two numbers; or,
198
- - Concatenation of two strings
199
+ - Addition, subtraction, product and division of two numbers; or,
200
+ - Concatenation of two strings,
201
+ - (In)equality test of two Lox values
199
202
 
200
203
  ### Implemented statements
201
204
  Loxxy implements the following statements:
@@ -44,7 +44,7 @@ module Loxxy
44
44
  op = aBinaryExpr.operator
45
45
  operand2 = stack.pop
46
46
  operand1 = stack.pop
47
- implemented = %i[+ -].include?(op)
47
+ implemented = %i[+ - * / == !=].include?(op)
48
48
  if implemented && operand1.respond_to?(op)
49
49
  stack.push operand1.send(op, operand2)
50
50
  else
@@ -19,6 +19,22 @@ module Loxxy
19
19
  def false?
20
20
  true
21
21
  end
22
+
23
+ # Check for equality of a Lox False with another Lox object
24
+ # @param other [Datatype::BuiltinDatatype, FalseClass, Object]
25
+ # @return [Datatype::Boolean]
26
+ def ==(other)
27
+ falsey = other.kind_of?(False) || other.kind_of?(FalseClass)
28
+ falsey ? True.instance : False.instance
29
+ 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
22
38
  end # class
23
39
 
24
40
  False.instance.freeze # Make the sole instance immutable
@@ -7,8 +7,8 @@ module Loxxy
7
7
  module Datatype
8
8
  # Class for representing a Lox string of characters value.
9
9
  class LXString < BuiltinDatatype
10
- # Compare a Lox String with another Lox (or genuine Ruby) String
11
- # @param other [Datatype::LxString, String]
10
+ # Check the equality of a Lox String with another Lox object.
11
+ # @param other [Datatype::LxString, String, Object]
12
12
  # @return [Datatype::Boolean]
13
13
  def ==(other)
14
14
  case other
@@ -17,8 +17,21 @@ module Loxxy
17
17
  when String
18
18
  (value == other) ? True.instance : False.instance
19
19
  else
20
- err_msg = "Cannot compare a #{self.class} with #{other.class}"
21
- raise StandardError, err_msg
20
+ False.instance
21
+ end
22
+ end
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
22
35
  end
23
36
  end
24
37
 
@@ -14,6 +14,22 @@ module Loxxy
14
14
  super(nil)
15
15
  end
16
16
 
17
+ # Check the equality with another object.
18
+ # @param other [Datatype::BuiltinDatatype, NilClass, Object]
19
+ # @return [Datatype::Boolean]
20
+ def ==(other)
21
+ is_nil = other.kind_of?(Nil) || other.kind_of?(NilClass)
22
+ is_nil ? True.instance : False.instance
23
+ end
24
+
25
+ # Check the inequality with another object.
26
+ # @param other [Datatype::BuiltinDatatype, NilClass, Object]
27
+ # @return [Datatype::Boolean]
28
+ def !=(other)
29
+ is_nil = other.kind_of?(Nil) || other.kind_of?(NilClass)
30
+ is_nil ? False.instance : True.instance
31
+ end
32
+
17
33
  # Method called from Lox to obtain the text representation of nil.
18
34
  # @return [String]
19
35
  def to_str
@@ -7,21 +7,6 @@ module Loxxy
7
7
  module Datatype
8
8
  # Class for representing a Lox numeric value.
9
9
  class Number < BuiltinDatatype
10
- # Compare a Lox Number with another Lox (or genuine Ruby) Number
11
- # @param other [Datatype::Number, Numeric]
12
- # @return [Datatype::Boolean]
13
- def ==(other)
14
- case other
15
- when Number
16
- (value == other.value) ? True.instance : False.instance
17
- when Numeric
18
- (value == other) ? True.instance : False.instance
19
- else
20
- err_msg = "Cannot compare a #{self.class} with #{other.class}"
21
- raise StandardError, err_msg
22
- end
23
- end
24
-
25
10
  # Perform the addition of two Lox numbers or
26
11
  # one Lox number and a Ruby Numeric
27
12
  # @param other [Loxxy::Datatype::Number, Numeric]
@@ -54,6 +39,66 @@ module Loxxy
54
39
  end
55
40
  end
56
41
 
42
+ # Perform the multiplication of two Lox numbers or
43
+ # one Lox number and a Ruby Numeric
44
+ # @param other [Loxxy::Datatype::Number, Numeric]
45
+ # @return [Loxxy::Datatype::Number]
46
+ def *(other)
47
+ case other
48
+ when Number
49
+ self.class.new(value * other.value)
50
+ when Numeric
51
+ self.class.new(value * other)
52
+ else
53
+ err_msg = "'*': Operands must be numbers."
54
+ raise TypeError, err_msg
55
+ end
56
+ end
57
+
58
+ # Perform the division of two Lox numbers or
59
+ # one Lox number and a Ruby Numeric
60
+ # @param other [Loxxy::Datatype::Number, Numeric]
61
+ # @return [Loxxy::Datatype::Number]
62
+ def /(other)
63
+ case other
64
+ when Number
65
+ self.class.new(value / other.value)
66
+ when Numeric
67
+ self.class.new(value / other)
68
+ else
69
+ err_msg = "'/': Operands must be numbers."
70
+ raise TypeError, err_msg
71
+ end
72
+ end
73
+
74
+ # Check the equality of a Lox number object with another object
75
+ # @param other [Datatype::BuiltinDatatype, Numeric, Object]
76
+ # @return [Datatype::Boolean]
77
+ def ==(other)
78
+ case other
79
+ when Number
80
+ (value == other.value) ? True.instance : False.instance
81
+ when Numeric
82
+ (value == other) ? True.instance : False.instance
83
+ else
84
+ False.instance
85
+ end
86
+ end
87
+
88
+ # Check the inequality of a Lox number object with another object
89
+ # @param other [Datatype::BuiltinDatatype, Numeric, Object]
90
+ # @return [Datatype::Boolean]
91
+ def !=(other)
92
+ case other
93
+ when Number
94
+ (value != other.value) ? True.instance : False.instance
95
+ when Numeric
96
+ (value != other) ? True.instance : False.instance
97
+ else
98
+ True.instance
99
+ end
100
+ end
101
+
57
102
  protected
58
103
 
59
104
  def validated_value(aValue)
@@ -19,6 +19,22 @@ module Loxxy
19
19
  def true?
20
20
  true
21
21
  end
22
+
23
+ # Check for equality of a Lox True with another Lox object
24
+ # @param other [Datatype::True, TrueClass, Object]
25
+ # @return [Datatype::Boolean]
26
+ def ==(other)
27
+ thruthy = other.kind_of?(True) || other.kind_of?(TrueClass)
28
+ thruthy ? True.instance : False.instance
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
22
38
  end # class
23
39
 
24
40
  True.instance.freeze # Make the sole instance immutable
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Loxxy
4
- VERSION = '0.0.15'
4
+ VERSION = '0.0.16'
5
5
  end
@@ -25,32 +25,88 @@ module Loxxy
25
25
  end
26
26
  end # context
27
27
 
28
- context 'Evaluating Lox code:' do
29
- let(:hello_world) { 'print "Hello, world!";' }
30
-
31
- it 'should evaluate core data types' do
32
- result = subject.evaluate('true; // Not false')
33
- expect(result).to be_kind_of(Loxxy::Datatype::True)
34
- end
35
-
28
+ context 'Evaluating arithmetic operations code:' do
36
29
  it 'should evaluate an addition of two numbers' do
37
30
  result = subject.evaluate('123 + 456; // => 579')
38
31
  expect(result).to be_kind_of(Loxxy::Datatype::Number)
39
32
  expect(result == 579).to be_true
40
33
  end
41
34
 
42
- it 'should evaluate a substraction of two numbers' do
35
+ it 'should evaluate a subtraction of two numbers' do
43
36
  result = subject.evaluate('4 - 3; // => 1')
44
37
  expect(result).to be_kind_of(Loxxy::Datatype::Number)
45
38
  expect(result == 1).to be_true
46
39
  end
47
40
 
41
+ it 'should evaluate a multiplication of two numbers' do
42
+ result = subject.evaluate('5 * 3; // => 15')
43
+ expect(result).to be_kind_of(Loxxy::Datatype::Number)
44
+ expect(result == 15).to be_true
45
+ end
46
+
47
+ it 'should evaluate a division of two numbers' do
48
+ result = subject.evaluate('8 / 2; // => 4')
49
+ expect(result).to be_kind_of(Loxxy::Datatype::Number)
50
+ expect(result == 4).to be_true
51
+ end
52
+ end # context
53
+
54
+ context 'Evaluating Lox code:' do
55
+ let(:hello_world) { 'print "Hello, world!";' }
56
+
57
+ it 'should evaluate core data types' do
58
+ result = subject.evaluate('true; // Not false')
59
+ expect(result).to be_kind_of(Loxxy::Datatype::True)
60
+ end
61
+
48
62
  it 'should evaluate string concatenation' do
49
63
  result = subject.evaluate('"str" + "ing"; // => "string"')
50
64
  expect(result).to be_kind_of(Loxxy::Datatype::LXString)
51
65
  expect(result == 'string').to be_true
52
66
  end
53
67
 
68
+ it 'should perform the equality tests of two values' do
69
+ [
70
+ ['nil == nil;', true],
71
+ ['true == true;', true],
72
+ ['true == false;', false],
73
+ ['1 == 1;', true],
74
+ ['1 == 2;', false],
75
+ ['0 == 0;', true],
76
+ ['"str" == "str";', true],
77
+ ['"str" == "ing";', false],
78
+ ['"" == "";', true],
79
+ ['nil == false;', false],
80
+ ['false == 0;', false],
81
+ ['0 == "0";', false]
82
+ ].each do |(source, predicted)|
83
+ lox = Loxxy::Interpreter.new
84
+ result = lox.evaluate(source)
85
+ expect(result.value == predicted).to be_truthy
86
+ end
87
+ end
88
+
89
+ it 'should perform the inequality test of two values' do
90
+ [
91
+ ['nil != nil;', false],
92
+ ['true != true;', false],
93
+ ['true != false;', true],
94
+ ['1 != 1;', false],
95
+ ['1 != 2;', true],
96
+ ['0 != 0;', false],
97
+ ['"str" != "str";', false],
98
+ ['"str" != "ing";', true],
99
+ ['"" != "";', false],
100
+ ['nil != false;', true],
101
+ ['false != 0;', true],
102
+ ['0 != "0";', true]
103
+ ].each do |(source, predicted)|
104
+ lox = Loxxy::Interpreter.new
105
+ result = lox.evaluate(source)
106
+ expect(result.value == predicted).to be_truthy
107
+ end
108
+ end
109
+
54
110
  it 'should print the hello world message' do
55
111
  expect { subject.evaluate(hello_world) }.not_to raise_error
56
112
  expect(sample_cfg[:ostream].string).to eq('Hello, world!')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loxxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.0.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef