Skip to content

Instantly share code, notes, and snippets.

@bcardiff
Created October 18, 2019 19:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bcardiff/4327823bb43cbb93734fbb6240315dac to your computer and use it in GitHub Desktop.
Save bcardiff/4327823bb43cbb93734fbb6240315dac to your computer and use it in GitHub Desktop.
module Listify
macro included
property prev : Pointer({{@type}}) = Pointer({{@type}}).null
property next : Pointer({{@type}}) = Pointer({{@type}}).null
end
def init_empty_list
@prev = @next = self_pointer
end
def empty?
@next == self_pointer
end
def each
return if empty?
e_ptr = @next
while (e = e_ptr.value) && e.next != e_ptr
yield e
e_ptr = e.next
end
yield e
end
private def self_pointer
(->self.itself).closure_data.as(Pointer(self))
end
macro prepend(list, item)
if {{list}}.empty?
{{item}}.next = pointerof({{item}})
else
old_first = {{list}}.next
{{item}}.next = old_first
old_first.value.prev = pointerof({{item}})
end
{{item}}.prev = pointerof({{list}})
{{list}}.next = pointerof({{item}})
end
macro remove(item)
if {{item}}.empty?
{{item}}.prev.value.next = {{item}}.prev
else
{{item}}.prev.value.next = {{item}}.next
{{item}}.next.value.prev = {{item}}.prev
end
{{item}}.prev = Pointer(typeof({{item}})).null
{{item}}.next = Pointer(typeof({{item}})).null
end
end
struct Foo
include Listify
property foo : Int32
def initialize(@foo : Int32)
end
end
struct Bar
include Listify
property bar : String
def initialize(@bar : String)
end
end
l = uninitialized Foo
l.init_empty_list
f2 = Foo.new(foo: 2)
f3 = Foo.new(foo: 3)
pp! l.empty?
Listify.prepend(l, f3)
Listify.prepend(l, f2)
pp! l.empty?
l.each { |e| pp! e.foo }
Listify.remove(f2)
pp! l.empty?
l.each { |e| pp e.foo }
Listify.remove(f3)
pp! l.empty?
l.each { |e| pp e.foo }
l2 = uninitialized Bar
l2.init_empty_list
b2 = Bar.new(bar: "2")
b3 = Bar.new(bar: "3")
pp! l2.empty?
Listify.prepend(l2, b3)
Listify.prepend(l2, b2)
pp! l2.empty?
l2.each { |e| pp! e.bar }
Listify.remove(b2)
pp! l2.empty?
l2.each { |e| pp e.bar }
Listify.remove(b3)
pp! l2.empty?
l2.each { |e| pp e.bar }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment