carbon-core 0.1.1 → 0.2.0

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 (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