Class: Lisp::Equivalence

Inherits:
Object show all
Defined in:
lib/rubylisp/equivalence.rb

Class Method Summary collapse

Class Method Details

.eq_check(o1, o2) ⇒ Object

eq? - identity, typically used for symbols



57
58
59
60
61
62
63
64
65
# File 'lib/rubylisp/equivalence.rb', line 57

def self.eq_check(o1, o2)
  return Lisp::FALSE unless o1.type == o2.type
  Lisp::Boolean.with_value(case o1.type
                           when :number
                             (o1.integer? == o2.integer?) && (o1.value == o2.value)
                           else
                             o1.equal?(o2)
                           end)
end

.eq_impl(args, env) ⇒ Object



68
69
70
71
72
73
# File 'lib/rubylisp/equivalence.rb', line 68

def self.eq_impl(args, env)
  raise "eq? needs 2 arguments, received #{args.length}" if args.length != 2
  o1 = args.car.evaluate(env)
  o2 = args.cadr.evaluate(env)
  eq_check(o1, o2)
end

.equal_check(o1, o2) ⇒ Object

equal? - object equality: same value



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/rubylisp/equivalence.rb', line 93

def self.equal_check(o1, o2)
  return Lisp::FALSE unless o1.type == o2.type
  Lisp::Boolean.with_value(case o1.type
                           when :pair
                             o1.eq?(o2)
                           when :string
                             o1.value.eql?(o2.value)
                           when :frame
                             o1.eq?(o2)
                           when :number
                             (o1.integer? == o2.integer?) && (o1.value == o2.value)
                           else
                             o1.equal?(o2)
                           end)
end

.equal_impl(args, env) ⇒ Object



110
111
112
113
114
115
# File 'lib/rubylisp/equivalence.rb', line 110

def self.equal_impl(args, env)
  raise "equal? needs 2 arguments, received #{args.length}" if args.length != 2
  o1 = args.car.evaluate(env)
  o2 = args.cadr.evaluate(env)
  self.equal_check(o1, o2)
end

.eqv_check(o1, o2) ⇒ Object

eqv? - same as eq?



78
79
80
# File 'lib/rubylisp/equivalence.rb', line 78

def self.eqv_check(o1, o2)
  eq_check(o1, o2)
end

.eqv_impl(args, env) ⇒ Object



83
84
85
86
87
88
# File 'lib/rubylisp/equivalence.rb', line 83

def self.eqv_impl(args, env)
  raise "eq? needs 2 arguments, received #{args.length}" if args.length != 2
  o1 = args.car.evaluate(env)
  o2 = args.cadr.evaluate(env)
  eqv_check(o1, o2)
end

.num_eq_impl(args, env) ⇒ Object

- Check two integers for equivalence



38
39
40
41
42
43
44
# File 'lib/rubylisp/equivalence.rb', line 38

def self.num_eq_impl(args, env)
  raise "= and == need 2 arguments, received #{args.length}" if args.length != 2
  c1 = args.car.evaluate(env)
  c2 = args.cadr.evaluate(env)
  return Lisp::FALSE unless c1.integer? && c2.integer?
  Lisp::Boolean.with_value(c1.value == c2.value)
end

.num_neq_impl(args, env) ⇒ Object



46
47
48
49
50
51
52
# File 'lib/rubylisp/equivalence.rb', line 46

def self.num_neq_impl(args, env)
  raise "!= and /= needs 2 arguments, received #{args.length}" if args.length != 2
  c1 = args.car.evaluate(env)
  c2 = args.cadr.evaluate(env)
  return Lisp::TRUE unless c1.integer? && c2.integer?
  Lisp::Boolean.with_value(c1.value != c2.value)
end

.registerObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/rubylisp/equivalence.rb', line 5

def self.register
  Primitive.register("=", "(= number number)\n\nReturns whether the first numeric argument is equal to the second numeric argument.") do |args, env|
    Lisp::Equivalence::num_eq_impl(args, env)
  end
  
  Primitive.register("==", "(== number number)\n\nReturns whether the first numeric argument is equal to the second numeric argument.") do |args, env|
    Lisp::Equivalence::num_eq_impl(args, env)
  end
  
  Primitive.register("!=", "(!= number number)\n\nReturns whether the first numeric argument is not equal to the second numeric argument.") do |args, env|
    Lisp::Equivalence::num_neq_impl(args, env)
  end
  
  Primitive.register("/=", "(/= number number)\n\nReturns whether the first numeric argument is not equal to the second numeric argument.") do |args, env|
    Lisp::Equivalence::num_neq_impl(args, env)
  end

  Primitive.register("eq?", "(eq? sexpr sexpr)\n\nReturns whether the first argument is the same type as the second argument, and the same object, except in the case of numbers where the values are compared.") do |args, env|
    Lisp::Equivalence::eq_impl(args, env)
  end
  
  Primitive.register("eqv?", "(eqv? sexpr sexpr)\n\nReturns whether the first argument is the same type as the second argument, and the same object, except in the case of numbers where the values are compared.") do |args, env|
    Lisp::Equivalence::eqv_impl(args, env)
  end
  
  Primitive.register("equal?", "(equal? sexpr sexpr)\n\nReturns whether the first argument is the same type as the second argument, and are lists containing the same elements, are identical strings, are frames with matching slots, are numbers with the same value, or are the same object (if none of the above).") do |args, env|
    Lisp::Equivalence::equal_impl(args, env)
  end
  
end