hammock-ruby 0.0.1.alpha

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.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +132 -0
  3. data/bin/hammock +55 -0
  4. data/lib/clojure/core.clj +6872 -0
  5. data/lib/hammock.rb +0 -0
  6. data/lib/hammock/aref.rb +57 -0
  7. data/lib/hammock/array_chunk.rb +49 -0
  8. data/lib/hammock/atom.rb +50 -0
  9. data/lib/hammock/block.rb +8 -0
  10. data/lib/hammock/chunk_buffer.rb +25 -0
  11. data/lib/hammock/chunked_cons.rb +108 -0
  12. data/lib/hammock/chunked_seq.rb +97 -0
  13. data/lib/hammock/compiler.rb +197 -0
  14. data/lib/hammock/environment.rb +40 -0
  15. data/lib/hammock/errors.rb +14 -0
  16. data/lib/hammock/function.rb +187 -0
  17. data/lib/hammock/ichunked_seq.rb +23 -0
  18. data/lib/hammock/ideref.rb +5 -0
  19. data/lib/hammock/ifn.rb +10 -0
  20. data/lib/hammock/ilookup.rb +6 -0
  21. data/lib/hammock/interfaces.rb +80 -0
  22. data/lib/hammock/ipersistent_collection.rb +15 -0
  23. data/lib/hammock/ireference.rb +15 -0
  24. data/lib/hammock/iseq.rb +12 -0
  25. data/lib/hammock/lazy_sequence.rb +82 -0
  26. data/lib/hammock/lazy_transformer.rb +169 -0
  27. data/lib/hammock/list.rb +232 -0
  28. data/lib/hammock/loop_locals.rb +34 -0
  29. data/lib/hammock/map.rb +205 -0
  30. data/lib/hammock/meta.rb +12 -0
  31. data/lib/hammock/multi_method.rb +52 -0
  32. data/lib/hammock/namespace.rb +185 -0
  33. data/lib/hammock/reader.rb +570 -0
  34. data/lib/hammock/recur_locals.rb +16 -0
  35. data/lib/hammock/reduced.rb +15 -0
  36. data/lib/hammock/repl.rb +29 -0
  37. data/lib/hammock/rt.rb +580 -0
  38. data/lib/hammock/sequence.rb +59 -0
  39. data/lib/hammock/set.rb +144 -0
  40. data/lib/hammock/stream.rb +40 -0
  41. data/lib/hammock/symbol.rb +65 -0
  42. data/lib/hammock/var.rb +186 -0
  43. data/lib/hammock/vector.rb +309 -0
  44. data/lib/hammock/version.rb +3 -0
  45. data/lib/hammock/volatile.rb +19 -0
  46. data/spec/examples/data.hmk +4 -0
  47. data/spec/hammock/reader_spec.rb +242 -0
  48. data/spec/hammock/rt_spec.rb +10 -0
  49. data/spec/hammock/sequence_spec.rb +24 -0
  50. metadata +139 -0
@@ -0,0 +1,59 @@
1
+ require 'hammock/meta'
2
+ require 'hammock/list'
3
+
4
+ module Hammock
5
+ class Sequence
6
+ include List
7
+ include Meta
8
+
9
+ attr_reader :head, :tail
10
+
11
+ def self.from_array(array, meta=nil)
12
+ return EmptyList.new(meta) if array.nil? || array.empty?
13
+ ret = array.to_a.reverse.inject(EmptyList.new) do |prev, el|
14
+ new(el, prev)
15
+ end
16
+ ret.with_meta(meta)
17
+ end
18
+
19
+ def self.alloc_from(other, meta=nil)
20
+ new(other.head, other.tail, meta)
21
+ end
22
+
23
+ def initialize(head, tail = Hammock::EmptyList.new, meta=nil)
24
+ @meta = meta
25
+ @head = head
26
+ @tail = tail
27
+ end
28
+
29
+ def car
30
+ head
31
+ end
32
+
33
+ def cdr
34
+ tail
35
+ end
36
+
37
+ def ==(other)
38
+ return false unless other.respond_to?(:tail)
39
+ first == other.first && tail == other.tail
40
+ end
41
+
42
+ def seq
43
+ self
44
+ end
45
+
46
+ def with_meta(meta)
47
+ self.class.new(head, tail, meta)
48
+ end
49
+
50
+ def inspect
51
+ "(#{to_a.map(&:inspect).join(' ')})"
52
+ end
53
+ alias to_s inspect
54
+
55
+ def empty?
56
+ false
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,144 @@
1
+ require 'hamster/immutable'
2
+ require 'hamster/trie'
3
+
4
+ require 'hammock/ipersistent_collection'
5
+ require 'hammock/meta'
6
+ require 'hammock/ifn'
7
+ require 'hammock/ilookup'
8
+
9
+ module Hammock
10
+ class Set
11
+ include Hamster::Immutable
12
+ include IPersistentCollection
13
+ include Meta
14
+ include IFn
15
+ include ILookup
16
+
17
+ Undefined = Object.new
18
+
19
+ def self.alloc_from(other, meta=nil)
20
+ new(meta, other.instance_variable_get(:@trie))
21
+ end
22
+
23
+ def self.create(coll)
24
+ if self === coll
25
+ coll
26
+ else
27
+ from_array(coll.to_a)
28
+ end
29
+ end
30
+
31
+ def self.from_array(items, meta=nil)
32
+ items.reduce(new(meta)) { |set, item| set.add(item) }
33
+ end
34
+
35
+ def initialize(meta=nil, trie=Hamster::EmptyTrie)
36
+ @meta = meta
37
+ @trie = trie
38
+ end
39
+
40
+ def empty?
41
+ @trie.empty?
42
+ end
43
+
44
+ def size
45
+ @trie.size
46
+ end
47
+ alias count size
48
+ alias length size
49
+
50
+ def add(item)
51
+ transform_unless(include?(item)) { @trie = @trie.put(item, nil) }
52
+ end
53
+ alias conj add
54
+ alias cons add
55
+
56
+ def delete(item)
57
+ trie = @trie.delete(item)
58
+ transform_unless(trie.equal?(@trie)) { @trie = trie }
59
+ end
60
+ alias remove delete
61
+ alias disjoin delete
62
+
63
+ def each
64
+ return self unless block_given?
65
+ @trie.each { |entry| yield(entry.key) }
66
+ end
67
+
68
+ def map
69
+ return self unless block_given?
70
+ return self if empty?
71
+ transform do
72
+ @trie = @trie.reduce(Hamster::EmptyTrie) do |trie, entry|
73
+ trie.put(yield(entry.key), nil)
74
+ end
75
+ end
76
+ end
77
+
78
+ def reduce(memo = Undefined)
79
+ each do |item|
80
+ memo = memo.equal?(Undefined) ? item : yield(memo, item)
81
+ end if block_given?
82
+ memo unless memo.equal?(Undefined)
83
+ end
84
+
85
+ def any?
86
+ return any? { |item| item } unless block_given?
87
+ each { |item| return true if yield(item) }
88
+ false
89
+ end
90
+
91
+ def include?(object)
92
+ has_key?(object)
93
+ end
94
+
95
+ def has_key?(key)
96
+ @trie.has_key?(key)
97
+ end
98
+ alias key? has_key?
99
+
100
+ def fetch(object, default=Undefined)
101
+ if has_key?(object)
102
+ object
103
+ elsif !default.equal?(Undefined)
104
+ default
105
+ end
106
+ end
107
+ alias call fetch
108
+ alias val_at fetch
109
+
110
+ def get(object)
111
+ object if has_key?(object)
112
+ end
113
+
114
+ def seq
115
+ return if count == 0
116
+ Sequence.from_array(to_a)
117
+ end
118
+
119
+ def eql?(other)
120
+ instance_of?(other.class) && @trie.eql?(other.instance_variable_get(:@trie))
121
+ end
122
+ alias == eql?
123
+
124
+ def hash
125
+ reduce(0) { |hash, item| (hash << 5) - hash + item.hash }
126
+ end
127
+
128
+ def empty
129
+ self.class.new(meta)
130
+ end
131
+
132
+ def to_a
133
+ ret = []
134
+ each do |obj|
135
+ ret << obj
136
+ end
137
+ ret
138
+ end
139
+
140
+ def inspect
141
+ "\#{#{to_a.map(&:inspect).join(' ')}}"
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,40 @@
1
+ require 'hammock/list'
2
+ require 'forwardable'
3
+
4
+ module Hammock
5
+ class Stream
6
+ extend Forwardable
7
+ include List
8
+ include Meta
9
+
10
+ def initialize(meta=nil, &block)
11
+ @meta = meta
12
+ @block = block
13
+ @lock = Mutex.new
14
+ end
15
+
16
+ def_delegators :target, :head, :tail, :empty?
17
+
18
+ protected
19
+
20
+ def vivify
21
+ @lock.synchronize do
22
+ unless @block.nil?
23
+ @target = @block.call
24
+ @block = nil
25
+ end
26
+ end
27
+ @target
28
+ end
29
+
30
+ private
31
+
32
+ def target
33
+ list = vivify
34
+ while list.is_a?(Stream)
35
+ list = list.vivify
36
+ end
37
+ list
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,65 @@
1
+ module Hammock
2
+ class Symbol
3
+ include Meta
4
+
5
+ attr_reader :name, :ns
6
+
7
+ def self.intern(*args)
8
+ return args.first if Hammock::Symbol === args.first
9
+
10
+ if args.length == 1
11
+ *ns, name = args.first.split("/", 2)
12
+ new(ns.first, name)
13
+ else
14
+ new(*args)
15
+ end
16
+ end
17
+
18
+ def self.alloc_from(other, meta)
19
+ new(other.instance_variable_get("@ns"), other.name, meta)
20
+ end
21
+
22
+ def initialize(ns, name, meta=nil)
23
+ @name = name
24
+ @ns = ns if ns && !ns.to_s.empty?
25
+ @name.freeze
26
+ @ns.freeze
27
+ @meta = meta
28
+ end
29
+
30
+ def ==(other)
31
+ return false unless other.respond_to?(:name)
32
+ return false unless other.respond_to?(:ns)
33
+ other.ns == ns && other.name == name
34
+ end
35
+ alias eql? ==
36
+
37
+ def constant
38
+ return @constant if defined?(@constant)
39
+ n = name.gsub(".", "::")
40
+ @constant = begin
41
+ Object.const_defined?(n) && Object.const_get(n)
42
+ rescue NameError
43
+ end
44
+ end
45
+
46
+ def inspect
47
+ @to_s ||= if @ns
48
+ "#@ns/#@name"
49
+ else
50
+ name
51
+ end
52
+ end
53
+ alias to_s inspect
54
+
55
+ def namespace(contextual=nil)
56
+ inns = Hammock::RT::CURRENT_NS.deref
57
+ prefer_ns = contextual || inns
58
+ if @ns
59
+ prefer_ns.lookup_alias(@ns) || Namespace.find(@ns)
60
+ else
61
+ prefer_ns
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,186 @@
1
+ require 'atomic'
2
+ require 'hammock/ideref'
3
+ require 'hammock/errors'
4
+ require 'hammock/map'
5
+
6
+ module Hammock
7
+ class Var
8
+ include Meta
9
+ include IFn
10
+ Undefined = Object.new
11
+
12
+ BINDING_KEY = "__bindings__".freeze
13
+
14
+ class Frame
15
+ attr_reader :bindings, :prev
16
+ def initialize(bindings, prev)
17
+ @bindings, @prev = bindings, prev
18
+ end
19
+ TOP = new(Map.new, nil)
20
+ end
21
+
22
+ def self.dvals
23
+ Thread.current[BINDING_KEY] ||= Frame::TOP
24
+ end
25
+
26
+ def self.dvals=(vals)
27
+ Thread.current[BINDING_KEY] = vals
28
+ end
29
+
30
+ def self.thread_bindings
31
+ f = dvals
32
+ ret = Map.new
33
+ f.bindings.each do |k,v|
34
+ ret.assoc(k, v)
35
+ end
36
+ ret
37
+ end
38
+
39
+ def self.push_thread_bindings(bindings)
40
+ f = dvals
41
+ bmap = f.bindings
42
+ bindings.each do |v,val|
43
+ if !v.dynamic?
44
+ raise Error, "Can't dynamically bind non-dynamic var: #{v.inspect}"
45
+ end
46
+ v.thread_bound!
47
+ bmap = bmap.assoc(v, val)
48
+ end
49
+ self.dvals = Frame.new(bmap, f)
50
+ end
51
+
52
+ def self.pop_thread_bindings
53
+ f = dvals.prev
54
+ if f.nil?
55
+ raise Error, "Pop without matching push"
56
+ else
57
+ self.dvals = f
58
+ end
59
+ end
60
+
61
+ def self.intern(ns_name, sym, val=Undefined)
62
+ if Namespace === ns_name
63
+ ns = ns_name
64
+ else
65
+ ns = Namespace.find_or_create(ns_name)
66
+ end
67
+
68
+ var = ns.intern(sym)
69
+ var.bind_root(val) unless val == Undefined
70
+ var
71
+ end
72
+
73
+ def self.find(ns_qualified_sym)
74
+ unless ns = ns_qualified_sym.ns
75
+ raise Error, "Symbol must be namespace-qualified"
76
+ end
77
+ unless namespace = Namespace.find(ns)
78
+ raise Error, "No such namespace: #{ns}"
79
+ end
80
+ namespace.find_var(ns_qualified_sym.name)
81
+ end
82
+
83
+ attr_reader :ns, :symbol, :root
84
+
85
+ def initialize(*args)
86
+ if args.length > 1
87
+ @ns, @symbol, @root = args
88
+ else
89
+ @root = args.first
90
+ end
91
+
92
+ @meta = nil
93
+ @dynamic = false
94
+ @public = true
95
+ @thread_bound = Atomic.new(false)
96
+ @rev = 0
97
+ end
98
+
99
+ alias namespace ns
100
+
101
+ def trace
102
+ return unless meta
103
+ "#{meta[:file]}:#{meta[:line]} in #@symbol"
104
+ end
105
+
106
+ def macro!
107
+ @meta = meta.assoc :macro, true
108
+ end
109
+
110
+ def dynamic!
111
+ @dynamic = true
112
+ self
113
+ end
114
+
115
+ def thread_bound!
116
+ @thread_bound.value = true
117
+ end
118
+
119
+ def thread_bound?
120
+ @thread_bound.value
121
+ end
122
+
123
+ def thread_binding
124
+ if thread_bound?
125
+ self.class.dvals.bindings[self]
126
+ end
127
+ end
128
+
129
+ def bound?
130
+ root? || (thread_bound? && self.class.dval.bindings.key?(self))
131
+ end
132
+
133
+ def root?
134
+ @rev > 0
135
+ end
136
+
137
+ def dynamic?
138
+ @dynamic
139
+ end
140
+
141
+ def public?
142
+ @public
143
+ end
144
+
145
+ def private?
146
+ !@public
147
+ end
148
+
149
+ def deref
150
+ thread_binding || @root
151
+ end
152
+
153
+ def bind_root(val)
154
+ @rev += 1
155
+ @root = val
156
+ end
157
+
158
+ def unbind_root
159
+ @root = nil
160
+ end
161
+
162
+ def meta=(meta)
163
+ if meta[:private]
164
+ @public = false
165
+ end
166
+ if meta[:dynamic]
167
+ @dynamic = true
168
+ end
169
+ @meta = meta
170
+ end
171
+
172
+ def call(*args)
173
+ @root.call(*args)
174
+ end
175
+
176
+ def to_s
177
+ if @ns
178
+ "#'#{@ns.name}/#{symbol.name}"
179
+ else
180
+ n = symbol ? symbol.to_s : "--unnamed--"
181
+ "#<Var: #{n}>"
182
+ end
183
+ end
184
+ alias inspect to_s
185
+ end
186
+ end