Class: Lisp::ConsCell

Inherits:
Object show all
Includes:
Enumerable
Defined in:
lib/rubylisp/cons_cell.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(car = nil, cdr = nil) ⇒ ConsCell

Returns a new instance of ConsCell.



16
17
18
19
# File 'lib/rubylisp/cons_cell.rb', line 16

def initialize(car=nil, cdr=nil)
  @car = car
  @cdr = cdr
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



202
203
204
205
206
207
208
# File 'lib/rubylisp/cons_cell.rb', line 202

def method_missing(name, *args, &block)
  if name[0] == ?c && name[-1] == ?r && (name[1..-2].chars.all? {|e| "ad".include?(e)})
    self.traverse(name[1..-2].reverse)
  else
    super
  end
end

Instance Attribute Details

#carObject (readonly)

Returns the value of attribute car.



5
6
7
# File 'lib/rubylisp/cons_cell.rb', line 5

def car
  @car
end

#cdrObject (readonly)

Returns the value of attribute cdr.



5
6
7
# File 'lib/rubylisp/cons_cell.rb', line 5

def cdr
  @cdr
end

Class Method Details

.array_to_list(cells, tail = nil) ⇒ Object



180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/rubylisp/cons_cell.rb', line 180

def self.array_to_list(cells, tail=nil)
  return cons() if cells.empty? && tail.nil?
  head = ConsCell.new
  last_cell = head
  (0...cells.length).each do |i|
    new_cell = self.cons(cells[i], nil)
    last_cell.set_cdr!(new_cell)
    last_cell = new_cell
  end
  last_cell.set_cdr!(tail)
  head.cdr
end

.cons(a = nil, b = nil) ⇒ Object



11
12
13
14
# File 'lib/rubylisp/cons_cell.rb', line 11

def self.cons(a=nil, b=nil)
  b = nil if b.pair? && b.empty?
  ConsCell.new(a, b)
end

Instance Method Details

#character?Boolean

Returns:



54
55
56
# File 'lib/rubylisp/cons_cell.rb', line 54

def character?
  false
end

#each(&block) ⇒ Object



169
170
171
172
173
174
175
176
177
178
# File 'lib/rubylisp/cons_cell.rb', line 169

def each &block
  return if empty?
  c = self
  if self.length > 0
    until c.nil?
      yield c.car 
      c = c.cdr
    end
  end
end

#empty?Boolean

Returns:



46
47
48
# File 'lib/rubylisp/cons_cell.rb', line 46

def empty?
  @car.nil? && @cdr.nil?
end

#eq?(other) ⇒ Boolean

Returns:



110
111
112
113
# File 'lib/rubylisp/cons_cell.rb', line 110

def eq?(other)
  return true if empty? && (other.nil? || (other.pair? && other.empty?))
  other.pair? && self == other
end

#equal?(other) ⇒ Boolean

Returns:



120
121
122
123
124
# File 'lib/rubylisp/cons_cell.rb', line 120

def equal?(other)
  return true if empty? && (other.nil? || (other.pair? && other.empty?))
  return false unless other.pair?
  @car.equal?(other.car) && @cdr.equal?(other.cdr)
end

#eqv?(other) ⇒ Boolean

Returns:



115
116
117
118
# File 'lib/rubylisp/cons_cell.rb', line 115

def eqv?(other)
  return true if empty? && (other.nil? || (other.pair? && other.empty?))
  other.pair? && self == other
end

#evaluate(env) ⇒ Object



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/rubylisp/cons_cell.rb', line 256

def evaluate(env)
  return self if empty?
  sexpr = if @car.symbol?
            throw :named_let_application, @cdr.to_a.map {|a| a.evaluate(env)} if @car.eq?(Lisp.named_let_stack[-1])
            key = @car
            frame = nth(1)
            value = nth(2)
            
            s = key.name
            if s.end_with?(":")
              ConsCell.array_to_list([Symbol.named("get-slot"), frame, key])
            elsif s.end_with?(":!")
              ConsCell.array_to_list([Symbol.named("set-slot!"), frame, Symbol.named(s[0..-2]), value])
            elsif s.end_with?(":?")
              ConsCell.array_to_list([Symbol.named("has-slot?"), frame, Symbol.named(s[0..-2])])
            elsif s.end_with?(":>")
              ConsCell.array_to_list([Symbol.named("send"), frame, Symbol.named(s[0..-2])] << self.cdddr)
            elsif s.end_with?(":^")
              ConsCell.array_to_list([Symbol.named("send-super"), frame, Symbol.named(s[0..-2])] << self.cdddr)
            else
              self
            end
          else
            self
          end
  sexpr.inner_eval(env)
end

#evaluate_each(env) ⇒ Object



284
285
286
287
288
289
# File 'lib/rubylisp/cons_cell.rb', line 284

def evaluate_each(env)
  return nil if empty?
  result = @car.evaluate(env)
  return result if @cdr.nil?
  @cdr.evaluate_each(env)
end

#false?Boolean

Returns:



301
302
303
# File 'lib/rubylisp/cons_cell.rb', line 301

def false?
  false
end

#flattenObject



321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/rubylisp/cons_cell.rb', line 321

def flatten
  ary = []
  to_a.each do |s|
    if s.nil?
      ary << nil
    elsif s.list?
      s.to_a.each {|e| ary << e}
    else
      ary << s
    end
  end
  ConsCell.array_to_list(ary)
end

#frame?Boolean

Returns:



102
103
104
# File 'lib/rubylisp/cons_cell.rb', line 102

def frame?
  false
end

#function?Boolean

Returns:



86
87
88
# File 'lib/rubylisp/cons_cell.rb', line 86

def function?
  false
end

#inner_eval(env) ⇒ Object



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/rubylisp/cons_cell.rb', line 233

def inner_eval(env)
  func = @car.evaluate(env)
  return Lisp::Debug.process_error("There is no function or macro named #{@car}", env) if func.nil?
  push_current_code if !Lisp::Debug.eval_in_debug_repl && Lisp::Debug.interactive

  Lisp::Debug.log_eval(self, env)
  
  unless Lisp::Debug.eval_in_debug_repl
    if !Lisp::Debug.target_env.nil? && env == Lisp::Debug.target_env.previous
      Lisp::Debug.target_env = nil
      Lisp::Debug.debug_repl(env)
    elsif Lisp::Debug.single_step || (func.function? && Lisp::Debug.on_entry.include?(func.name))
      Lisp::Debug.debug_repl(env)
    end
  end

  result = func.apply_to(@cdr, env)
  env.pop_code if !Lisp::Debug.eval_in_debug_repl && Lisp::Debug.interactive
  Lisp::Debug.log_result(result, env)
  result
end

#lastObject



309
310
311
312
313
314
315
# File 'lib/rubylisp/cons_cell.rb', line 309

def last
  c = self
  while !c.cdr.nil? && c.cdr.pair? do
    c = c.cdr
  end
  c
end

#lengthObject



291
292
293
294
295
# File 'lib/rubylisp/cons_cell.rb', line 291

def length
  return 0 if empty?
  return 1 if @cdr.nil?
  return 1 + @cdr.length
end

#lisp_object?Boolean

Returns:



29
30
31
# File 'lib/rubylisp/cons_cell.rb', line 29

def lisp_object?
  true
end

#list?Boolean

Returns:



98
99
100
# File 'lib/rubylisp/cons_cell.rb', line 98

def list?
  true
end

#macro?Boolean

Returns:



90
91
92
# File 'lib/rubylisp/cons_cell.rb', line 90

def macro?
  false
end

#negative?Boolean

Returns:



70
71
72
# File 'lib/rubylisp/cons_cell.rb', line 70

def negative?
  false
end

#nth(n) ⇒ Object



210
211
212
213
214
# File 'lib/rubylisp/cons_cell.rb', line 210

def nth(n)
  c = self
  n.times {|i| c = c.cdr}
  c.car
end

#nth_tail(n) ⇒ Object



216
217
218
219
220
# File 'lib/rubylisp/cons_cell.rb', line 216

def nth_tail(n)
  c = self
  n.times {|i| c = c.cdr}
  c
end

#number?Boolean

Returns:



58
59
60
# File 'lib/rubylisp/cons_cell.rb', line 58

def number?
  false
end

#objc_object_or_nil(obj) ⇒ Object



222
223
224
225
# File 'lib/rubylisp/cons_cell.rb', line 222

def objc_object_or_nil(obj)
  return nil unless obj.object?
  return obj.value
end

#pair?Boolean

Returns:



94
95
96
# File 'lib/rubylisp/cons_cell.rb', line 94

def pair?
  true
end

#positive?Boolean

Returns:



62
63
64
# File 'lib/rubylisp/cons_cell.rb', line 62

def positive?
  false
end

#primitive?Boolean

Returns:



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

def primitive?
  false
end


317
318
319
# File 'lib/rubylisp/cons_cell.rb', line 317

def print_ary(a)
  (0...a.length).map {|i| puts (a[i].nil? ? "nil" : a[i])}
end


149
150
151
152
153
154
155
156
# File 'lib/rubylisp/cons_cell.rb', line 149

def print_string
  return "()" if self.empty?
  return "'#{@cdr.car.print_string}" if @car.symbol? && @car.name == "quote"
  return "{#{@cdr.print_string_helper}}" if @car.symbol? && @car.name == "make-frame"
  return "#(#{@cdr.print_string_helper})" if @car.symbol? && @car.name == "make-vector"
  return "(#{@car.print_string} . #{@cdr.print_string})" if !@cdr.nil? && !@cdr.pair?
  return "(#{self.print_string_helper})"
end


145
146
147
# File 'lib/rubylisp/cons_cell.rb', line 145

def print_string_helper
  @cdr.nil? ? "#{@car.print_string}" : "#{@car.print_string} #{@cdr.print_string_helper}"
end

#push_current_codeObject



228
229
230
# File 'lib/rubylisp/cons_cell.rb', line 228

def push_current_code
  env.push_code(self.print_string)
end

#quotedObject



305
306
307
# File 'lib/rubylisp/cons_cell.rb', line 305

def quoted
  Lisp::ConsCell.array_to_list([Symbol.named("quote"), self])
end

#set_car!(d) ⇒ Object



25
26
27
# File 'lib/rubylisp/cons_cell.rb', line 25

def set_car!(d)
  @car = d
end

#set_cdr!(d) ⇒ Object



33
34
35
# File 'lib/rubylisp/cons_cell.rb', line 33

def set_cdr!(d)
  @cdr = d
end

#set_location(type, package, file, start, length) ⇒ Object



7
8
# File 'lib/rubylisp/cons_cell.rb', line 7

def set_location(type, package, file, start, length)
end

#set_nth!(n, d) ⇒ Object



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

def set_nth!(n, d)
  return nil if empty?
  c = self
  n.times {|i| c = c.cdr}
  c.set_car!(d)
end

#special?Boolean

Returns:



82
83
84
# File 'lib/rubylisp/cons_cell.rb', line 82

def special?
  false
end

#string?Boolean

Returns:



50
51
52
# File 'lib/rubylisp/cons_cell.rb', line 50

def string?
  false
end

#symbol?Boolean

Returns:



74
75
76
# File 'lib/rubylisp/cons_cell.rb', line 74

def symbol?
  false
end

#to_aObject



158
159
160
161
162
163
164
165
166
167
# File 'lib/rubylisp/cons_cell.rb', line 158

def to_a
  a = []
  return a if empty?
  c = self
  until c.nil?
    a << c.car
    c = c.cdr
  end
  a
end

#to_sObject



136
137
138
139
140
141
142
143
# File 'lib/rubylisp/cons_cell.rb', line 136

def to_s
  return "()" if self.empty?
  return "'#{@cdr.car.to_s}" if @car.symbol? && @car.name == "quote"
  return "{#{@cdr.to_s_helper}}" if @car.symbol? && @car.name == "make-frame"
  return "#(#{@cdr.to_s_helper})" if @car.symbol? && @car.name == "make-vector"
  return "(#{@car.to_s} . #{@cdr.to_s})" if !@cdr.nil? && !@cdr.pair?
  return "(#{self.to_s_helper})"
end

#to_s_helperObject



130
131
132
133
134
# File 'lib/rubylisp/cons_cell.rb', line 130

def to_s_helper
  return "#{@car.to_s}" if @cdr.nil?
  return "#{@car.to_s} . #{@cdr.to_s}" unless @cdr.pair?
  "#{@car.to_s} #{@cdr.to_s_helper}"
end

#traverse(path) ⇒ Object



193
194
195
196
197
198
199
200
# File 'lib/rubylisp/cons_cell.rb', line 193

def traverse(path)
  next_cell = self
  path.chars.each do |p|
    return nil if next_cell.nil?  || !next_cell.pair?
    next_cell = ((p == ?a) ? next_cell.car : next_cell.cdr)
  end
  next_cell
end

#true?Boolean

Returns:



297
298
299
# File 'lib/rubylisp/cons_cell.rb', line 297

def true?
  true
end

#typeObject



126
127
128
# File 'lib/rubylisp/cons_cell.rb', line 126

def type
  :pair
end

#valueObject



21
22
23
# File 'lib/rubylisp/cons_cell.rb', line 21

def value
  self
end

#vector?Boolean

Returns:



106
107
108
# File 'lib/rubylisp/cons_cell.rb', line 106

def vector?
  false
end

#zero?Boolean

Returns:



66
67
68
# File 'lib/rubylisp/cons_cell.rb', line 66

def zero?
  false
end