hammock-ruby 0.0.1.alpha

Sign up to get free protection for your applications and to get access to all the features.
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