carbon-core 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +17 -0
  3. data/.gitignore +0 -0
  4. data/.rspec +0 -0
  5. data/.rubocop.yml +0 -0
  6. data/.travis.yml +0 -0
  7. data/.yardopts +0 -0
  8. data/CODE_OF_CONDUCT.md +0 -0
  9. data/Gemfile +0 -0
  10. data/LICENSE.txt +0 -0
  11. data/README.md +0 -0
  12. data/Rakefile +0 -0
  13. data/Vagrantfile +0 -0
  14. data/carbon.gemspec +0 -0
  15. data/lib/carbon.rb +25 -1
  16. data/lib/carbon/concrete.rb +4 -2
  17. data/lib/carbon/concrete/build.rb +21 -13
  18. data/lib/carbon/concrete/index.rb +53 -159
  19. data/lib/carbon/concrete/item.rb +0 -0
  20. data/lib/carbon/concrete/item/base.rb +14 -27
  21. data/lib/carbon/concrete/item/class.rb +71 -0
  22. data/lib/carbon/concrete/item/class/element.rb +42 -0
  23. data/lib/carbon/concrete/item/data.rb +0 -0
  24. data/lib/carbon/concrete/item/function.rb +35 -39
  25. data/lib/carbon/concrete/item/internal.rb +17 -19
  26. data/lib/carbon/concrete/item/struct.rb +12 -7
  27. data/lib/carbon/concrete/item/struct/element.rb +0 -0
  28. data/lib/carbon/concrete/item/trait.rb +9 -10
  29. data/lib/carbon/concrete/item/trait/expectation.rb +0 -0
  30. data/lib/carbon/concrete/request.rb +137 -136
  31. data/lib/carbon/concrete/type.rb +126 -21
  32. data/lib/carbon/concrete/type/function.rb +26 -10
  33. data/lib/carbon/concrete/type/generic.rb +19 -3
  34. data/lib/carbon/concrete/type/name.rb +0 -0
  35. data/lib/carbon/concrete/type/parse.rb +1 -0
  36. data/lib/carbon/concrete/type/part.rb +9 -1
  37. data/lib/carbon/core.rb +6 -1
  38. data/lib/carbon/core/int.rb +0 -0
  39. data/lib/carbon/core/integer.rb +0 -0
  40. data/lib/carbon/core/integer/cast.rb +0 -0
  41. data/lib/carbon/core/integer/math.rb +0 -0
  42. data/lib/carbon/core/integer/misc.rb +17 -1
  43. data/lib/carbon/core/integer/pole.rb +0 -0
  44. data/lib/carbon/core/integer/ship.rb +8 -4
  45. data/lib/carbon/core/integer/sign.rb +0 -0
  46. data/lib/carbon/core/integer/type.rb +0 -0
  47. data/lib/carbon/core/integer/zero.rb +0 -0
  48. data/lib/carbon/core/main.rb +50 -0
  49. data/lib/carbon/core/pointer.rb +0 -0
  50. data/lib/carbon/core/pointer/access.rb +1 -1
  51. data/lib/carbon/core/pointer/cast.rb +0 -0
  52. data/lib/carbon/core/pointer/math.rb +14 -0
  53. data/lib/carbon/core/pointer/memory.rb +2 -4
  54. data/lib/carbon/core/pointer/type.rb +0 -0
  55. data/lib/carbon/core/void.rb +20 -0
  56. data/lib/carbon/counter.rb +27 -0
  57. data/lib/carbon/errors.rb +13 -0
  58. data/lib/carbon/tacky.rb +0 -0
  59. data/lib/carbon/tacky/block.rb +0 -0
  60. data/lib/carbon/tacky/builder.rb +3 -6
  61. data/lib/carbon/tacky/context.rb +4 -10
  62. data/lib/carbon/tacky/function.rb +0 -24
  63. data/lib/carbon/tacky/instruction.rb +2 -5
  64. data/lib/carbon/tacky/instruction/generation.rb +19 -41
  65. data/lib/carbon/tacky/parameter.rb +0 -0
  66. data/lib/carbon/tacky/reference.rb +0 -0
  67. data/lib/carbon/tacky/typed.rb +0 -0
  68. data/lib/carbon/tacky/value.rb +0 -2
  69. data/lib/carbon/version.rb +1 -1
  70. data/scripts/core.rb +0 -0
  71. data/scripts/test.rb +5 -7
  72. metadata +9 -4
  73. data/lib/carbon/tacky/instruction/dependencies.rb +0 -33
  74. data/lib/carbon/tacky/instruction/typeof.rb +0 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d19855dccc09339b3aab63ae8189dd7d2c8be42d
4
- data.tar.gz: e83a47d93719cea99bc46e972ee5cc2be8d23ab9
3
+ metadata.gz: 8365acf735d2c50dee428d024b4a840c1c6161e7
4
+ data.tar.gz: 279f5819696b66cd4e7add773d8afc8a75409ea7
5
5
  SHA512:
6
- metadata.gz: d167ad893b767cbe85fbece99c690f71b824c3847070122c162bb64559ccbc567ebd4c7ebdb4596c3a211f069cfe14caf8e60428f328736c2eaae631ebd5a1b0
7
- data.tar.gz: d01280b2758d932ded3fb9399f009fbaa968ae115cbf69b415a2aaadb59926f809f96105cf876fbec474aa131ed814a5cc7d6fdccb1e1dc748b02fc936257bde
6
+ metadata.gz: 0b429250034abeca6ee48306e4ce461cfc432ac622f6ef0471c8efa7c9e40baa5016559672660258ea90fcd93f92d7ccfe39d852a9fefb34b3dc9b4ffaa6aa4a
7
+ data.tar.gz: 3e9e619482e2303cc9643a7c73eb5417982a285986a329b6509e521278b76a6e45c91c32b40b48154625fbc3dabbea38eb56c29c90a9b8747d29f507007964e1
data/.gitattributes ADDED
@@ -0,0 +1,17 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
3
+
4
+ # Custom for Visual Studio
5
+ *.cs diff=csharp
6
+
7
+ # Standard to msysgit
8
+ *.doc diff=astextplain
9
+ *.DOC diff=astextplain
10
+ *.docx diff=astextplain
11
+ *.DOCX diff=astextplain
12
+ *.dot diff=astextplain
13
+ *.DOT diff=astextplain
14
+ *.pdf diff=astextplain
15
+ *.PDF diff=astextplain
16
+ *.rtf diff=astextplain
17
+ *.RTF diff=astextplain
data/.gitignore CHANGED
File without changes
data/.rspec CHANGED
File without changes
data/.rubocop.yml CHANGED
File without changes
data/.travis.yml CHANGED
File without changes
data/.yardopts CHANGED
File without changes
data/CODE_OF_CONDUCT.md CHANGED
File without changes
data/Gemfile CHANGED
File without changes
data/LICENSE.txt CHANGED
File without changes
data/README.md CHANGED
File without changes
data/Rakefile CHANGED
File without changes
data/Vagrantfile CHANGED
File without changes
data/carbon.gemspec CHANGED
File without changes
data/lib/carbon.rb CHANGED
@@ -9,6 +9,8 @@ require "concurrent"
9
9
  require "llvm"
10
10
  require "llvm/core"
11
11
  require "carbon/version"
12
+ require "carbon/counter"
13
+ require "carbon/errors"
12
14
 
13
15
  # Carbon. The language.
14
16
  module Carbon
@@ -37,11 +39,26 @@ module Carbon
37
39
  # @param string [::String] The string to hash.
38
40
  # @return [::String] The hashed string.
39
41
  def self.hash(string)
40
- digest = Digest::SHA2.hexdigest(string).hex
42
+ digest = (Digest::SHA2.hexdigest(string).hex << 6) ^ 0xCA5B04
41
43
  encoded = Base58.encode(digest)
42
44
  encoded.scan(/.{1,9}/).join("-").freeze
43
45
  end
44
46
 
47
+ # The verboseness of Carbon. This is a global setting.
48
+ #
49
+ # @return [::Integer] The verboseness.
50
+ def self.verbose
51
+ @_verbose ||= 1
52
+ end
53
+
54
+ # The verboseness of Carbon. This is a global setting.
55
+ #
56
+ # @param verbose [::Integer] The new verbose level.
57
+ # @return [::Integer]
58
+ def self.verbose=(verbose)
59
+ @_verbose = verbose
60
+ end
61
+
45
62
  require "carbon/concrete"
46
63
 
47
64
  # A Boolean type for Carbon. This is used as a handy shortcut.
@@ -50,6 +67,13 @@ module Carbon
50
67
  # @return [Carbon::Concrete::Type]
51
68
  Boolean = Carbon::Type("Carbon::Boolean")
52
69
 
70
+ # A Void type for Carbon. This is used as a handy shortcut.
71
+ #
72
+ # @api private
73
+ # @return [Carbon::Concrete::Type]
74
+
75
+ Void = Carbon::Type("Carbon::Void")
76
+
53
77
  require "carbon/tacky"
54
78
  require "carbon/core"
55
79
  end
@@ -14,6 +14,8 @@ module Carbon
14
14
  # the things within this module should be serializable, so that libraries
15
15
  # may be linked easily back into the process.
16
16
  module Concrete
17
+ OPTIONS = { circular: true, class_cache: true }.freeze
18
+
17
19
  # Loads a dumped object into an instance. The dumped object should be a
18
20
  # Zlib compressed (with Deflate) string. The dumped object
19
21
  # is decompressed and loaded, then passed to {.from}.
@@ -24,7 +26,7 @@ module Carbon
24
26
  # @return [::Object] The represented object.
25
27
  def self.load(source)
26
28
  raw = Zlib::Inflate.inflate(source)
27
- Oj.load(raw)
29
+ Oj.load(raw, OPTIONS)
28
30
  end
29
31
 
30
32
  # Dumps an object to a string. If the object responds to `#to_basic`, the
@@ -36,7 +38,7 @@ module Carbon
36
38
  # @param index [::Object] The object to dump.
37
39
  # @return [::String] The dumped object.
38
40
  def self.dump(index)
39
- raw = Oj.dump(index, circular: true, class_cache: true)
41
+ raw = Oj.dump(index, OPTIONS)
40
42
  Zlib::Deflate.deflate(raw, 9)
41
43
  end
42
44
  end
@@ -14,24 +14,23 @@ module Carbon
14
14
  # corresponding `LLVM::Type`. This is so that no information is lost
15
15
  # when converting the item to the type.
16
16
  #
17
- # @return [{Concrete::Type => (Concrete::Item, ::LLVM::Type)}]
18
- attr_reader :types
19
-
20
- # The functions that have been defined. This is a mapping of the
21
- # {Concrete::Type} to the `LLVM::Function` that was defined.
22
- #
23
- # @return [{Concrete::Type => (Concrete::Item, ::LLVM::Function)}]
24
- attr_reader :functions
17
+ # @return [{Concrete::Type => (Concrete::Item, ::LLVM::Value)}]
18
+ attr_reader :items
25
19
 
26
20
  # The LLVM module that is being used for compilation.
27
21
  #
28
22
  # @return [::LLVM::Module]
29
23
  attr_reader :module
30
24
 
25
+ # The index associated with this build.
26
+ #
27
+ # @return [Concrete::Index]
28
+ attr_reader :index
29
+
31
30
  # Initialize the build process. This only initializes instance
32
31
  # variables.
33
32
  #
34
- # @param requests [::Enumerable<Concrete::Request>] An enumerable over
33
+ # @param requests [::Enumerable<Concrete::Type>] An enumerable over
35
34
  # each request that needs to be built. The requests should be
36
35
  # resolved, i.e. the generics for the request should resolve to a
37
36
  # valid type.
@@ -41,18 +40,27 @@ module Carbon
41
40
  @index = index
42
41
  end
43
42
 
43
+ def fetch(name, default = nil)
44
+ result = @items.find { |(k, _v)| k.match?(name) }
45
+
46
+ return result[1] if result
47
+ return default if default
48
+ yield if block_given?
49
+ fail ItemNotFoundError, "Could not find item with name #{name}"
50
+ end
51
+
44
52
  # Performs the build process. Builds each request in order by calling
45
53
  # {Concrete::Item::Base#call} on each.
46
54
  #
47
55
  # @return [::LLVM::Module] The built module.
48
56
  def call
49
- @types = {}
50
- @functions = {}
57
+ @items = {}
51
58
  @module = ::LLVM::Module.new("__carbon_main")
52
59
 
53
60
  @requests.each do |request|
54
- item = @index.fetch(request.intern)
55
- generics = item.generics.zip(request.generics).to_h
61
+ item = @index.fetch(request).first
62
+ generics = item.generics.map(&:name)
63
+ .zip(request.generics.map(&:name)).to_h
56
64
  item.call(self, generics)
57
65
  end
58
66
 
@@ -14,6 +14,7 @@ module Carbon
14
14
  class Index
15
15
  include TSort
16
16
  extend Forwardable
17
+ include Enumerable
17
18
 
18
19
  # We can't use these methods because we don't fit the bill - we don't
19
20
  # define a `tsort_each_node`, since we don't need it. We only use
@@ -27,6 +28,8 @@ module Carbon
27
28
  undef_method :each_strongly_connected_component
28
29
  undef_method :strongly_connected_components
29
30
 
31
+ delegate [:each] => :items
32
+
30
33
  # Initialize the index with the given data.
31
34
  #
32
35
  # @api public
@@ -36,95 +39,45 @@ module Carbon
36
39
  # completely derived from the index itself; or, rather, what's defined
37
40
  # on the index. See {#id}.
38
41
  def initialize(data = {})
39
- @items = Concurrent::Hash.new.merge(data.fetch(:items, {}))
42
+ @items = ::Set.new.merge(data.fetch(:items, []))
43
+ @links = ::Set.new
40
44
  @id = data.fetch(:id) { id }
41
- mutex
42
45
  end
43
46
 
44
- # @overload fetch(name, default = CANARY)
45
- # Retrieves the item with the given symbol name. If no item with the
46
- # given name exists, it tries the following: first, if a block is
47
- # given, the item name is yielded to the block, and the result is
48
- # returned. Second, if the second argument is passed (i.e. isn't
49
- # `CANARY`), then that is returned instead. Third, if neither is
50
- # true, then the method raises `KeyError`.
51
- #
52
- # @api public
53
- # @example Successful fetch.
54
- # index.fetch("Carbon::Integer") # => #<Carbon::Concrete::Item::Base>
55
- # @example Failed fetch with argument.
56
- # index.fetch("Carbon::Foo", false) # => false
57
- # @example Failed fetch with block.
58
- # index.fetch("Carbon::Foo") { |n| n.sub("F", "B") }
59
- # # => "Carbon::Boo"
60
- # @example Failed fetch with both.
61
- # index.fetch("Carbon::Foo", false) { |n| n.sub("F", "B") }
62
- # # => "Carbon::Boo"
63
- # @param name [::Object] The key of the item to fetch.
64
- # @param default [::Object] The value to return if the key doesn't match
65
- # an item and a block wasn't given.
66
- # @yield [name] If the key doesn't match an item, the method yields.
67
- # @yieldparam name [::Object] The name of the item.
68
- # @return [::Object] The item, if the key matched; otherwise, the result
69
- # of the block, if given; otherwise, the value of the `default`
70
- # parameter.
71
- # @raise [KeyError] If the key doesn't match an item and neither a
72
- # block nor the second argument were passed.
73
- def fetch(*options, &block)
74
- mutex.synchronize { @items.fetch(*options, &block) }
75
- end
47
+ @canary = ::Object.new
48
+ def fetch(type, default = @canary)
49
+ matching = items.map { |i| [i, i.type.match?(type)] }.select(&:last)
50
+ fail TooManyItemsError, "Multiple items match #{type}" if
51
+ matching.size > 1
52
+ match = matching.first
76
53
 
77
- # @overload [](key)
78
- # Retrieves the item with the given symbol name. If no item exists,
79
- # it returns `nil`.
80
- #
81
- # @api public
82
- # @example Successful retrieval.
83
- # index["Carbon::Integer"] # => #<Carbon::Concrete::Item::Base>
84
- # @example Unsuccessful retrieval.
85
- # index["Carbon::Foo"] # => nil
86
- # @param key [::Object] The key of the item to lookup.
87
- # @return [::Object] The item, if it exists;
88
- # @return [nil] Otherwise.
89
- def [](*options)
90
- mutex.synchronize { @items[*options] }
54
+ return match if match
55
+ return yield if block_given?
56
+ return default if default != @canary
57
+ fail ItemNotFoundError, "Could not find an item named #{type}"
91
58
  end
92
59
 
93
- # @overload key?(key)
94
- # Determines whether or not the key exists, and an item is paired
95
- # with it.
96
- #
97
- # @api public
98
- # @example Existing key.
99
- # index.key?("Carbon::Integer") # => true
100
- # @example Non-existant key.
101
- # index.key?("Carbon::Foo") # => false
102
- # @param key [::Object] The key of the item to check.
103
- # @return [::Boolean] Whether the key exists or not.
104
- def key?(*options)
105
- mutex.synchronize { @items.key?(*options) }
60
+ def item?(type)
61
+ items.any? { |item| item.type.match?(type) }
106
62
  end
107
63
 
108
- # Returns all of the keys in the index. The keys and the array itself
109
- # are both frozen.
110
- #
111
- # @api public
112
- # @example
113
- # index.keys # => ["Carbon::Boolean", "Carbon::Integer"]
114
- # @return [<::String>] The keys in the index.
115
- def keys
116
- mutex.synchronize { @items.keys.deep_freeze! }
64
+ def items
65
+ @_current ||= begin
66
+ current = @items.dup
67
+ @links.each do |link|
68
+ current.merge(link.items)
69
+ end
70
+
71
+ current.freeze
72
+ end
117
73
  end
118
74
 
119
- # Returns all of the values (actual items) in the index. The items, and
120
- # the array containing them, are frozen.
121
- #
122
- # @api public
123
- # @example
124
- # index.values.map(&:class) # => [Carbon::Concrete::Item::Internal, ...]
125
- # @return [<Item::Base>] The values in the index.
126
- def values
127
- mutex.synchornize { @items.values.freeze }
75
+ def to_json
76
+ links, @links = @links, nil
77
+ clear! && id
78
+ value = Oj.dump(self, Concrete::OPTIONS)
79
+ @links = links
80
+ value
128
81
  end
129
82
 
130
83
  # The digest of the ID. This uses the SHA256 base58 digest of the items
@@ -133,23 +86,14 @@ module Carbon
133
86
  #
134
87
  # @api public
135
88
  # @example
136
- # index.items # => {}
89
+ # index.items # => []
137
90
  # index.id # => "gjNT5GbSC-81KmUPncw-hzQAGV3GU-eAXafmkMP-Bw2GMHWM"
138
91
  # @return [::String]
139
92
  def id
140
- @id ||= Carbon.hash(items.keys.join("\n"))
141
- end
142
-
143
- # The items of the index. This is a frozen duplicate of the items.
144
- # Therefore, this is not guarenteed to be up to date.
145
- #
146
- # @api public
147
- # @example Items
148
- # index.items
149
- # # => {"Carbon::Integer" => #<Carbon::Concrete::Item::Base>}
150
- # @return [{::String => Item::Base}] The items of the index.
151
- def items
152
- mutex.synchronize { @items.dup.deep_freeze! }
93
+ @_id ||= begin
94
+ body = (@items.map(&:type).map(&:to_s) + @links.map(&:id)).join("\n")
95
+ Carbon.hash(body)
96
+ end
153
97
  end
154
98
 
155
99
  # Adds a defined item to the index. The item just has to respond to
@@ -161,41 +105,18 @@ module Carbon
161
105
  # @example Adding an item.
162
106
  # index << item
163
107
  # index.key?(item.intern) # => true
164
- # @example Merging an index.
165
- # other.is_a?(Carbon::Concrete::Index) # => true
166
- # index << other
167
- # index.items.keys.to_set <= other.items.keys.to_set
168
- # @note
169
- # If the item is an index instead, it passes it to {#merge} and
170
- # returns. This usage is not recommended for {#add}, but can be
171
- # used for {#<<}.
172
108
  # @param item [Concrete::Item::Base] The item to add.
173
109
  # @return [self]
174
110
  def add(item)
175
- return merge(item) if item.is_a?(Index)
176
- mutex.synchronize do
177
- @items[item.intern] = item
178
- clear!
179
- end
111
+ @items << item
112
+ clear!
180
113
  end
181
114
 
182
115
  alias_method :<<, :add
183
116
 
184
- # Merges items from another index into the merged items of this index.
185
- # This clears the index's cache, such that the ID ({#id}) have to be
186
- # recalculated.
187
- #
188
- # @api public
189
- # @example Merging.
190
- # index.merge(other)
191
- # index.items.keys.to_set <= other.items.keys.to_set
192
- # @param index [Index] The index to merge.
193
- # @return [self]
194
- def merge(index)
195
- mutex.synchronize do
196
- @items.merge(index.items)
197
- clear!
198
- end
117
+ def link(index)
118
+ @links << index
119
+ clear!
199
120
  end
200
121
 
201
122
  # Finalizes the index. This should only be used when all of the items
@@ -207,15 +128,10 @@ module Carbon
207
128
  # for this instance of the index.
208
129
  # @return [self]
209
130
  def finalize
210
- mutex.synchronize do
211
- items = @items.map do |key, value|
212
- [key, value.define(self)]
213
- end.to_h
214
-
215
- @items = items.freeze
216
- end
217
-
218
- self
131
+ current = @items.dup
132
+ items = ::Set.new(current.map { |item| item.define(self) })
133
+ @items = items.freeze
134
+ clear!
219
135
  end
220
136
 
221
137
  # Used only for {#define}. This maps item "names" to the classes that
@@ -280,47 +196,34 @@ module Carbon
280
196
  # request.intern # => "Main"
281
197
  # request.generics # => []
282
198
  # index.build(request).to_a # => [...]
283
- # @param item [Item::Base] The item to build. The {Item::Base} module
284
- # contains behavior that is required by this method (namely,
285
- # {Item::Base#corrected_dependencies}, {Item::Base#intern}, and
286
- # {Item::Base#generics}).
199
+ # @param item [Concrete::Type] The type to build.
287
200
  # @return [::Enumerable] The build items, if no block is given.
288
201
  # @return [void] If a block is given.
289
202
  # @yield [dep] Multiple times, each with a dependency.
290
203
  # @yieldparam dep [Request] A request.
291
204
  def build(item)
292
- mutex.lock
293
205
  fail ArgumentError, "Passed item cannot be generic" if \
294
206
  item.generics.any?
295
207
  return to_enum(:build, item) unless block_given?
296
- request = Request.new(item.intern, [])
297
208
 
298
- build_from_request(request, &Proc.new)
299
- ensure
300
- mutex.unlock
209
+ build_from_request(item, &Proc.new)
301
210
  end
302
211
 
303
212
  private
304
213
 
305
- def mutex
306
- @_mutex ||= ::Mutex.new
214
+ def clear!
215
+ @_id = @_current = nil
216
+ self
307
217
  end
308
218
 
309
- # rubocop:disable Metrics/MethodLength
310
219
  def build_from_request(request)
311
220
  components = to_enum(:each_strongly_connected_component_from, request)
312
221
  components.each do |group|
313
222
  fail TSort::Cyclic, "cyclic dependencies: #{group.join(', ')}" if \
314
223
  group.size > 1
315
- begin
316
- mutex.unlock
317
- yield group.first
318
- ensure
319
- mutex.lock
320
- end
224
+ yield group.first
321
225
  end
322
226
  end
323
- # rubocop:enable Metrics/MethodLength
324
227
 
325
228
  # Iterates over all of the "children" of a node. This iterates over all
326
229
  # of the corrected dependencies of a node, allowing the TSort module
@@ -332,16 +235,7 @@ module Carbon
332
235
  # @yieldparam request [Request]
333
236
  # @return [void]
334
237
  def tsort_each_child(node, &block)
335
- @items.fetch(node.intern).corrected_dependencies(node, &block)
336
- end
337
-
338
- # Clears the cache, forcing the id to be rebuilt on next call.
339
- #
340
- # @api private
341
- # @return [self]
342
- def clear!
343
- @id = nil
344
- self
238
+ fetch(node).first.corrected_dependencies(node, &block)
345
239
  end
346
240
  end
347
241
  end