Class: MiniKraken::Composite::ConsCell
- Inherits:
-
CompositeTerm
- Object
- MiniKraken::Core::BaseTerm
- MiniKraken::Core::Term
- CompositeTerm
- MiniKraken::Composite::ConsCell
- Defined in:
- lib/mini_kraken/composite/cons_cell.rb
Overview
In Lisp dialects, a cons cell (or a pair) is a data structure with two fields named car and cdr (for historical reasons). Cons cells are the key ingredient for building lists in Lisp. A cons cell can be depicted as a box with two parts, car and cdr each containing a reference to another object.
+-----------+
| car | cdr |
+--|-----|--+
| |
V V
obj1 obj2
The list (1 2 3) can be constructed as follows:
+-----------+
| car | cdr |
+--|-----|--+
| |
V V
1 +-----------+
| car | cdr |
+--|-----|--+
| |
V V
2 +-----------+
| car | cdr |
+--|-----|--+
| |
V V
3 nil
Instance Attribute Summary collapse
-
#car ⇒ Term
readonly
The first slot in a ConsCell.
-
#cdr ⇒ Term
readonly
The second slot in a ConsCell.
Class Method Summary collapse
-
.null ⇒ ConsCell
Specialized constructor for null list.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Return true if car and cdr fields have the same values as the other ConsCell.
- #children ⇒ Object
-
#dependencies(ctx) ⇒ Set<String>
Return the list of variable (i_names) that this term depends on.
-
#dup_cond(substitutions) ⇒ ConsCell
File ‘lib/mini_kraken/atomic/atomic_term.rb’, line 91 Make a copy of self with all the variable reference being replaced by the corresponding value in the Hash.
-
#eql?(other) ⇒ Boolean
Test for type and data value equality.
- #expand(ctx, theSubstitutions) ⇒ Object
-
#floating?(ctx) ⇒ Boolean
Does the composite have a variable that is itself floating?.
-
#initialize(obj1, obj2 = NullList) ⇒ ConsCell
constructor
Construct a new conscell whose car and cdr are obj1 and obj2.
-
#null? ⇒ Boolean
Return true if it is an empty list, otherwise false.
-
#pinned?(ctx) ⇒ Boolean
Does the cons cell have a definite value?.
-
#quote(anEnv) ⇒ ConsCell
Return a data object that is a copy of the ConsCell.
-
#set!(member, element) ⇒ Object
Set one element of the pair.
-
#set_car!(element) ⇒ Object
Change the car of ConsCell to ‘element’.
-
#set_cdr!(element) ⇒ Object
Change the cdr of ConsCell to ‘element’.
-
#to_s ⇒ String
Use the list notation from Lisp as a text representation.
-
#unbound?(_ctx) ⇒ FalseClass
Is the receiver an unbound variable? By definition, a composite isn’t a variable.
Constructor Details
#initialize(obj1, obj2 = NullList) ⇒ ConsCell
Construct a new conscell whose car and cdr are obj1 and obj2. In Scheme, a list is terminated by a null list. In MiniKraken, a list is terminated by a Ruby nil. Therefore, when setting the cdr to the null list, the implementation will silently replace the null list by a nil.
55 56 57 58 59 60 61 62 63 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 55 def initialize(obj1, obj2 = NullList) super() @car = obj1 if obj2.kind_of?(ConsCell) && obj2.null? @cdr = NullList else @cdr = obj2 end end |
Instance Attribute Details
#car ⇒ Term (readonly)
The first slot in a ConsCell
42 43 44 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 42 def car @car end |
#cdr ⇒ Term (readonly)
The second slot in a ConsCell
46 47 48 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 46 def cdr @cdr end |
Class Method Details
.null ⇒ ConsCell
Specialized constructor for null list.
67 68 69 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 67 def self.null new(nil, nil) end |
Instance Method Details
#==(other) ⇒ Boolean
Return true if car and cdr fields have the same values as the other ConsCell.
138 139 140 141 142 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 138 def ==(other) return false unless other.respond_to?(:car) (car == other.car) && (cdr == other.cdr) end |
#children ⇒ Object
100 101 102 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 100 def children [car, cdr] end |
#dependencies(ctx) ⇒ Set<String>
Return the list of variable (i_names) that this term depends on. For a variable reference, it will return the i_names of its variable
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 174 def dependencies(ctx) deps = [] visitor = ConsCellVisitor.df_visitor(self) skip_children = false loop do side, cell = visitor.resume(skip_children) if cell.kind_of?(Core::LogVarRef) deps << ctx.lookup(cell.name).i_name skip_children = true else skip_children = false end break if side == :stop end Set.new(deps) end |
#dup_cond(substitutions) ⇒ ConsCell
File ‘lib/mini_kraken/atomic/atomic_term.rb’, line 91 Make a copy of self with all the variable reference being replaced by the corresponding value in the Hash.
251 252 253 254 255 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 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 251 def dup_cond(substitutions) head = curr_cell = nil path = [] visitor = ConsCellVisitor.df_visitor(self) # Breadth-first! skip_children = false loop do side, cell = visitor.resume(skip_children) # next if cell == self break if side == :stop if cell.kind_of?(ConsCell) new_cell = ConsCell.null if curr_cell curr_cell.set!(side, new_cell) path.push(curr_cell) end curr_cell = new_cell head ||= new_cell else duplicate = cell.nil? ? nil : cell.dup_cond(substitutions) curr_cell.set!(side, duplicate) curr_cell = path.pop if side == :cdr end end head end |
#eql?(other) ⇒ Boolean
Test for type and data value equality.
147 148 149 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 147 def eql?(other) (self.class == other.class) && car.eql?(other.car) && cdr.eql?(other.cdr) end |
#expand(ctx, theSubstitutions) ⇒ Object
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 194 def (ctx, theSubstitutions) head = curr_cell = nil path = [] visitor = ConsCellVisitor.df_visitor(self) skip_children = false loop do side, cell = visitor.resume(skip_children) # next if cell == self break if side == :stop case cell when ConsCell new_cell = ConsCell.null if curr_cell curr_cell.set!(side, new_cell) path.push(curr_cell) unless side == :cdr else head = new_cell path.push(new_cell) end if side == :cdr && cell.null? curr_cell = path.pop else curr_cell = new_cell end when Core::LogVarRef # Is this robust? if cell.i_name i_name = cell.i_name else i_name = ctx.symbol_table.lookup(cell.name).i_name end = ctx.(i_name, theSubstitutions) curr_cell.set!(side, ) curr_cell = path.pop if side == :cdr else curr_cell.set!(side, cell) curr_cell = path.pop if side == :cdr end end head end |
#floating?(ctx) ⇒ Boolean
Does the composite have a variable that is itself floating?
121 122 123 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 121 def floating?(ctx) !pinned?(ctx) end |
#null? ⇒ Boolean
Return true if it is an empty list, otherwise false. A list is empty, when both car and cdr fields are nil.
107 108 109 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 107 def null? car.nil? && cdr.nil? end |
#pinned?(ctx) ⇒ Boolean
Does the cons cell have a definite value?
127 128 129 130 131 132 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 127 def pinned?(ctx) pinned_car = car.nil? || car.pinned?(ctx) pinned_cdr = cdr.nil? || cdr.pinned?(ctx) pinned_car && pinned_cdr end |
#quote(anEnv) ⇒ ConsCell
Return a data object that is a copy of the ConsCell
154 155 156 157 158 159 160 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 154 def quote(anEnv) return self if null? new_car = car.nil? ? nil : car.quote(anEnv) new_cdr = cdr.nil? ? nil : cdr.quote(anEnv) ConsCell.new(new_car, new_cdr) end |
#set!(member, element) ⇒ Object
Set one element of the pair
74 75 76 77 78 79 80 81 82 83 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 74 def set!(member, element) case member when :car set_car!(element) when :cdr set_cdr!(element) else raise StandardError, "Undefined cons cell member #{member}" end end |
#set_car!(element) ⇒ Object
Change the car of ConsCell to ‘element’. Analogue of set-car! procedure in Scheme.
88 89 90 91 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 88 def set_car!(element) @cdr = NullList if null? @car = element end |
#set_cdr!(element) ⇒ Object
Change the cdr of ConsCell to ‘element’. Analogue of set-cdr! procedure in Scheme.
96 97 98 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 96 def set_cdr!(element) @cdr = element end |
#to_s ⇒ String
Use the list notation from Lisp as a text representation.
164 165 166 167 168 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 164 def to_s return '()' if null? "(#{pair_to_s})" end |
#unbound?(_ctx) ⇒ FalseClass
Is the receiver an unbound variable? By definition, a composite isn’t a variable.
115 116 117 |
# File 'lib/mini_kraken/composite/cons_cell.rb', line 115 def unbound?(_ctx) false end |