carbon-core 0.1.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 (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +38 -0
  5. data/.travis.yml +4 -0
  6. data/.yardopts +1 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/Gemfile +11 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +41 -0
  11. data/Rakefile +14 -0
  12. data/carbon.gemspec +30 -0
  13. data/lib/carbon.rb +54 -0
  14. data/lib/carbon/concrete.rb +43 -0
  15. data/lib/carbon/concrete/build.rb +63 -0
  16. data/lib/carbon/concrete/index.rb +324 -0
  17. data/lib/carbon/concrete/item.rb +37 -0
  18. data/lib/carbon/concrete/item/base.rb +153 -0
  19. data/lib/carbon/concrete/item/data.rb +22 -0
  20. data/lib/carbon/concrete/item/function.rb +97 -0
  21. data/lib/carbon/concrete/item/internal.rb +83 -0
  22. data/lib/carbon/concrete/item/struct.rb +65 -0
  23. data/lib/carbon/concrete/item/struct/element.rb +42 -0
  24. data/lib/carbon/concrete/item/trait.rb +72 -0
  25. data/lib/carbon/concrete/item/trait/expectation.rb +55 -0
  26. data/lib/carbon/concrete/request.rb +137 -0
  27. data/lib/carbon/concrete/type.rb +260 -0
  28. data/lib/carbon/concrete/type/function.rb +91 -0
  29. data/lib/carbon/concrete/type/generic.rb +118 -0
  30. data/lib/carbon/concrete/type/name.rb +147 -0
  31. data/lib/carbon/concrete/type/parse.rb +172 -0
  32. data/lib/carbon/concrete/type/part.rb +100 -0
  33. data/lib/carbon/core.rb +61 -0
  34. data/lib/carbon/core/int.rb +87 -0
  35. data/lib/carbon/core/integer.rb +109 -0
  36. data/lib/carbon/core/integer/cast.rb +83 -0
  37. data/lib/carbon/core/integer/math.rb +198 -0
  38. data/lib/carbon/core/integer/misc.rb +145 -0
  39. data/lib/carbon/core/integer/pole.rb +133 -0
  40. data/lib/carbon/core/integer/ship.rb +71 -0
  41. data/lib/carbon/core/integer/sign.rb +52 -0
  42. data/lib/carbon/core/integer/type.rb +42 -0
  43. data/lib/carbon/core/integer/zero.rb +52 -0
  44. data/lib/carbon/core/pointer.rb +54 -0
  45. data/lib/carbon/core/pointer/access.rb +123 -0
  46. data/lib/carbon/core/pointer/cast.rb +55 -0
  47. data/lib/carbon/core/pointer/math.rb +187 -0
  48. data/lib/carbon/core/pointer/memory.rb +85 -0
  49. data/lib/carbon/core/pointer/type.rb +23 -0
  50. data/lib/carbon/tacky.rb +21 -0
  51. data/lib/carbon/tacky/block.rb +96 -0
  52. data/lib/carbon/tacky/builder.rb +310 -0
  53. data/lib/carbon/tacky/context.rb +66 -0
  54. data/lib/carbon/tacky/function.rb +137 -0
  55. data/lib/carbon/tacky/instruction.rb +170 -0
  56. data/lib/carbon/tacky/parameter.rb +23 -0
  57. data/lib/carbon/tacky/reference.rb +23 -0
  58. data/lib/carbon/tacky/value.rb +40 -0
  59. data/lib/carbon/version.rb +9 -0
  60. metadata +186 -0
@@ -0,0 +1,91 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Carbon
5
+ module Concrete
6
+ class Type
7
+ # The function part of a type. This comes after the module that it is
8
+ # defined in, and contains three pieces of information: the name of the
9
+ # function, the generics associated with the function, and the parameters
10
+ # of the function.
11
+ #
12
+ # @todo TODO: add generic parameters.
13
+ # @note
14
+ # **This class is frozen upon initialization.** This means that any
15
+ # attempt to modify it will result in an error. In most cases, the
16
+ # attributes on this class will also be frozen, as well.
17
+ # @note
18
+ # This class does not include comparison methods; however, if they
19
+ # were to ever be needed, {#to_s} should be used for the basis of
20
+ # comparison.
21
+ class Function
22
+ # The name of the function. This is normally a bland string.
23
+ # Functions can have a variety of names to override default operations
24
+ # in the language; even more so than ruby.
25
+ #
26
+ # @api public
27
+ # @example
28
+ # type = Carbon::Type("A.+(A, B)")
29
+ # func = type.name.function
30
+ # func.name # => "+"
31
+ # @return [::String] The name of the function.
32
+ attr_reader :name
33
+
34
+ # The parameters for the function. These are the arguments that are
35
+ # passed to the function when it's called. This is included in the
36
+ # definition for the name of the function to allow overloading.
37
+ #
38
+ # @api public
39
+ # @example
40
+ # type = Carbon::Type("A.+(A, B)")
41
+ # func = type.name.function
42
+ # func.parameters
43
+ # # => [#<Carbon::Concrete::Type::Name A>,
44
+ # # #<Carbon::Concrete::Type::Name B>]
45
+ # @return [::Array<Type::Name>]
46
+ attr_reader :parameters
47
+
48
+ # Initialize the function.
49
+ #
50
+ # @see #name
51
+ # @see #params
52
+ # @param name [::String] The name of the function.
53
+ # @param params [::Array<Type::Name>] The parameters of the function.
54
+ # This is frozen before stored.
55
+ def initialize(name, params)
56
+ @name = name
57
+ @parameters = params
58
+ deep_freeze!
59
+ end
60
+
61
+ # Returns a string representation of this function. In contrast to
62
+ # {#intern}, this includes generic information.
63
+ #
64
+ # @api public
65
+ # @example
66
+ # func.name # => "+"
67
+ # func.parameters # => [#<Carbon::Concrete::Type::Name Test<T>>]
68
+ # func.to_s # => "+(Test<T>)"
69
+ # @return [::String]
70
+ def to_s
71
+ "#{@name}(#{@parameters.map(&:to_s).join(', ')})".freeze
72
+ end
73
+
74
+ # Returns the interned version of this function. In contrast to
75
+ # {#to_s}, this does not include generic information.
76
+ #
77
+ # @api public
78
+ # @note See {Item::Base#intern} For more information about interned
79
+ # names.
80
+ # @example
81
+ # func.name # => "+"
82
+ # func.parameters # => [#<Carbon::Concrete::Type::Name Test<T>>]
83
+ # func.intern # => "+(Test)"
84
+ # @return [::String]
85
+ def intern
86
+ "#{@name}(#{@parameters.map(&:intern).join(', ')})".freeze
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,118 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Carbon
5
+ module Concrete
6
+ class Type
7
+ # A generic part of a type. This is normally the `T` in
8
+ # `Carbon::Pointer<T>`. Generic portions can also have traits that
9
+ # the generic type must implement; this keeps track of that too.
10
+ # A complete example, containing traits, would look like this:
11
+ # `Carbon::Pointer<T: Carbon::Sized + Carbon::Numeric>`. The actual
12
+ # pointer type may not use those traits.
13
+ #
14
+ # @note
15
+ # **This class is frozen upon initialization.** This means that any
16
+ # attempt to modify it will result in an error. In most cases, the
17
+ # attributes on this class will also be frozen, as well.
18
+ class Generic
19
+ # The name of the generic. This is the generic type variable that is
20
+ # substituted in later for an actual value. This is normally a single
21
+ # character module name, but can be as complicated as needed.
22
+ #
23
+ # @api public
24
+ # @example
25
+ # type = Carbon::Type("Carbon::Pointer<T>")
26
+ # type.generics.first.name # => #<Carbon::Concrete::Type T>
27
+ # @return [Type] The name.
28
+ attr_reader :name
29
+
30
+ # The implements of the generic. These are the traits that the generic
31
+ # parameter has to implement; this allows the generic code to make
32
+ # assumptions about the generic type (such as behavior or size) that
33
+ # would otherwise be impossible to make.
34
+ #
35
+ # @api public
36
+ # @example
37
+ # name = "Carbon::Pointer<T: Carbon::Sized>"
38
+ # type = Carbon::Type(name)
39
+ # type.generics.first.implements
40
+ # # => Set[#<Carbon::Concrete::Type Carbon::Sized>]
41
+ # @return [Set<Type>] The traits the generic has to implement.
42
+ attr_reader :implements
43
+
44
+ # Initialize the generic part of the type.
45
+ #
46
+ # @see #name
47
+ # @see #implements
48
+ # @param name [Type] The name of the generic.
49
+ # @param implements [Set<Type>] The traits the generic must
50
+ # implement, if any.
51
+ def initialize(name, implements)
52
+ @name = name
53
+ @implements = Set.new(implements)
54
+ deep_freeze!
55
+ end
56
+
57
+ # Returns the correct generic. This is a weird function, but
58
+ # essentially, if the {#name}'s {Type#intern} is oen of the keys of
59
+ # the mapping, it returns the new generic; otherwise, it returns
60
+ # this object.
61
+ #
62
+ # @api public
63
+ # @example
64
+ # generic.to_s # => "T: Carbon::Sized"
65
+ # generic.is_a?(Generic) # => true
66
+ # other.to_s # => "Carbon::String"
67
+ # other.is_a?(Generic) # => true
68
+ # result = generic.sub("T" => other)
69
+ # result.to_s # => "Carbon::String: Carbon::Sized"
70
+ # @param mapping [{::String => Type::Generic}] The mapping.
71
+ # @return [Type::Generic] A different instance of the generic, if it's
72
+ # in the mapping.
73
+ # @return [self] otherwise.
74
+ def sub(mapping)
75
+ mapping.fetch(@name.intern, self)
76
+ end
77
+
78
+ # Compares this generic instance to another generic instance. If the
79
+ # other generic instance _is_ this generic instance it returns true;
80
+ # otherwise, if the other value is a generic, and that generic's
81
+ # {#to_s} is equal to this one's, it returns true; otherwise, it
82
+ # returns false.
83
+ #
84
+ # @api public
85
+ # @example
86
+ # type1 = Carbon::Type("Carbon::Pointer<T>")
87
+ # type2 = Carbon::Type("Carbon::List<T>")
88
+ # type1.generics == type2.generics # => true
89
+ # @param other [Type::Generic, ::Object] The object to compare.
90
+ # @return [::Boolean] True if the two are equivalent.
91
+ def ==(other)
92
+ equal?(other) ||
93
+ (other.is_a?(Type::Generic) && other.to_s == to_s)
94
+ end
95
+
96
+ alias_method :eql?, :==
97
+
98
+ # A string representation of the generic. If there are no implements,
99
+ # this is a direct call to {#name}'s {Type#to_s}; otherwise, this
100
+ # includes the name with a joined string of implements.
101
+ #
102
+ # @api public
103
+ # @example
104
+ # name = "Carbon::Pointer<T: Carbon::Sized>"
105
+ # type = Carbon::Type(name)
106
+ # type.generics.first.to_s # => "T: Carbon::Sized"
107
+ # @return [::String] The string representation.
108
+ def to_s
109
+ if @implements.any?
110
+ "#{@name}: #{@implements.map(&:to_s).join(' + ')}".freeze
111
+ else
112
+ @name.to_s
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,147 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ module Carbon
5
+ module Concrete
6
+ class Type
7
+ # The "name" of a type. This contains all of the physical information
8
+ # of a type. This mostly means the "parts" for the name, and the
9
+ # function information if it is included.
10
+ #
11
+ # @note
12
+ # **This class is frozen upon initialization.** This means that any
13
+ # attempt to modify it will result in an error. In most cases, the
14
+ # attributes on this class will also be frozen, as well.
15
+ class Name
16
+ include Enumerable
17
+ extend Forwardable
18
+
19
+ # The parts of the name. This is mainly the sections of the type
20
+ # name; for example, for `Carbon::Pointer`, the parts are `Carbon` and
21
+ # `Pointer`. Each part can contain generic information; however,
22
+ # by convention, only the last part is actually included for generic
23
+ # information.
24
+ #
25
+ # @api semipublic
26
+ # @example
27
+ # type = Carbon::Type("Carbon::Pointer<T>")
28
+ # name = type.name
29
+ # name.parts
30
+ # # => [#<Carbon::Concrete::Type::Part Carbon>,
31
+ # # #<Carbon::Concrete::Type::Part Pointer>]
32
+ # @return [<Type::Part>] The parts.
33
+ attr_reader :parts
34
+
35
+ # The function information of a type. If no function information was
36
+ # included (i.e. the type is a module), then this is `nil`.
37
+ # Function information always includes a name and the parameters, if
38
+ # it is included.
39
+ #
40
+ # @api public
41
+ # @example
42
+ # full = "Carbon::Pointer<T>.+(Carbon::Pointer<T>, Carbon::Int32)"
43
+ # type = Carbon::Type(full)
44
+ # name = type.name
45
+ # name.function.to_s # => "+(Carbon::Pointer<T>, Carbon::Int32)"
46
+ # @return [Type::Function] The function information.
47
+ attr_reader :function
48
+
49
+ # @!method each
50
+ # Iterates over each part.
51
+ #
52
+ # @see #parts
53
+ # @api semipublic
54
+ # @example
55
+ # type.name.each { |part| puts part }
56
+ # @return [::Enumerable] An enumerable over the parts.
57
+ # @!method to_a
58
+ # Returns an array of the parts of the name.
59
+ #
60
+ # @see #parts
61
+ # @api semipublic
62
+ # @example
63
+ # type.name.to_a == type.name.parts # => true
64
+ # @return [<Type::Part>] The parts.
65
+ # @!method [](index)
66
+ # Returns a part at a specific index, or the parts over the given
67
+ # range.
68
+ #
69
+ # @see #parts
70
+ # @api semipublic
71
+ # @example
72
+ # type.name[0].to_s # => "Carbon"
73
+ # @param index [Numeric, Range<Numeric>]
74
+ # @return [Type::Part] The part.
75
+ # @return [<Type::Part>] The parts over the range.
76
+ # @!method first
77
+ # Returns the first part in the name.
78
+ #
79
+ # @see #parts
80
+ # @api semipublic
81
+ # @example
82
+ # type.name.first.to_s # => "Carbon"
83
+ # @return [Type::Part] The first part.
84
+ # @!method last
85
+ # Returns the last part in the name.
86
+ #
87
+ # @see #part
88
+ # @api semipublic
89
+ # @example
90
+ # type.name.last.to_s # => "Pointer<T>"
91
+ # @return [Type::Part] The last part.
92
+ delegate [:each, :to_a, :[], :first, :last] => :@parts
93
+
94
+ # Initialize the name with the given parts and function information.
95
+ # Freezes the class after completion.
96
+ #
97
+ # @param parts [<Type::Part>] The parts of the name.
98
+ # @param function [Type::Function?] The function part of the name, if
99
+ # it exists.
100
+ def initialize(parts, function)
101
+ @parts = parts.freeze
102
+ @function = function
103
+
104
+ to_s
105
+ intern
106
+ deep_freeze!
107
+ end
108
+
109
+ # A string representation of the name. Unlike {#intern}, this
110
+ # includes all generic information as well.
111
+ #
112
+ # @api public
113
+ # @example
114
+ # type = Carbon::Type("Carbon::Pointer<T>")
115
+ # type.to_s # => "Carbon::Pointer<T>"
116
+ # @return [::String] The string representation.
117
+ def to_s
118
+ @_to_s ||=
119
+ if @function
120
+ "#{@parts.map(&:to_s).join('::')}.#{@function}"
121
+ else
122
+ @parts.map(&:to_s).join("::")
123
+ end.freeze
124
+ end
125
+
126
+ # An interned name of the type. Unlike {#to_s}, this doesn't include
127
+ # any generic information.
128
+ #
129
+ # @api public
130
+ # @example
131
+ # type = Carbon::Type("Carbon::Pointer<T>")
132
+ # type.intern # => "Carbon::Pointer"
133
+ # @note See {Item::Base#intern} For more information about interned
134
+ # names.
135
+ # @return [::String] The interned name of the type.
136
+ def intern
137
+ @_intern ||=
138
+ if @function
139
+ "#{@parts.map(&:intern).join('::')}.#{@function.intern}"
140
+ else
141
+ @parts.map(&:intern).join("::")
142
+ end.freeze
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,172 @@
1
+ # encoding: utf-8
2
+ # frozen_string_literal: true
3
+ # rubocop:disable all
4
+
5
+ require "strscan"
6
+
7
+ module Carbon
8
+ module Concrete
9
+ class Type
10
+ # Parses a type. This starts by scanning the string, then parsing it.
11
+ # Each instance should result in a different parsed value; a single
12
+ # instance cannot be re-used for parsing something else. **Not for
13
+ # public consumption.**
14
+ #
15
+ # @api private
16
+ # @private
17
+ class Parse
18
+ # Initialize the parser.
19
+ #
20
+ # @param scan [::String] The string to parse.
21
+ def initialize(scan)
22
+ @string = scan
23
+ @scanner = StringScanner.new(@string)
24
+ end
25
+
26
+ # The resulting value. This should be a name.
27
+ #
28
+ # @see #parse
29
+ # @return [Type::Name]
30
+ def value
31
+ @_value ||= parse
32
+ end
33
+
34
+ private
35
+
36
+ def parse
37
+ @tokens = scan
38
+ name = parse_name
39
+ end
40
+
41
+ def scan
42
+ return to_enum(:scan) unless block_given?
43
+
44
+ until @scanner.eos?
45
+ single = scan_single
46
+ yield single if single
47
+ end
48
+
49
+ yield [:EOS]
50
+ end
51
+
52
+ def expect(*values)
53
+ token = @tokens.next
54
+ error(values, token[0]) unless values.include?(token[0])
55
+ token
56
+ end
57
+
58
+ def parse_name
59
+ parts = [parse_name_part]
60
+ func = nil
61
+
62
+ while @tokens.peek[0] == :"::"
63
+ expect :"::"
64
+ parts << parse_name_part
65
+ end
66
+
67
+ parts = [*parts[0..-2].map(&:strip), parts[-1]]
68
+ func = parse_function_name if @tokens.peek[0] == :"."
69
+
70
+ Name.new(parts, func)
71
+ end
72
+
73
+ def parse_function_name
74
+ name = nil
75
+ params = []
76
+ expect :"."
77
+ name = case @tokens.peek[0]
78
+ when :< then expect(:<); "<"
79
+ when :> then expect(:>); ">"
80
+ when :+ then expect(:+); "+"
81
+ else expect(:FNAME)[1]
82
+ end
83
+
84
+ expect :"("
85
+ until @tokens.peek[0] == :")"
86
+ params << Type.new(parse_name)
87
+ break unless @tokens.peek[0] == :","
88
+ expect :","
89
+ end
90
+ expect :")"
91
+
92
+ Function.new(name, params)
93
+ end
94
+
95
+ def parse_name_part
96
+ part = expect(:MNAME)
97
+ generics = []
98
+ if @tokens.peek[0] == :<
99
+ expect :<
100
+
101
+ until @tokens.peek[0] == :>
102
+ generics << parse_generic
103
+ break unless @tokens.peek[0] == :","
104
+ expect :","
105
+ end
106
+
107
+ expect :>
108
+ end
109
+
110
+ Part.new(part[1], generics)
111
+ end
112
+
113
+ def parse_generic
114
+ name = Type.new(parse_name)
115
+ implements = []
116
+ if @tokens.peek[0] == :":"
117
+ expect :":"
118
+ implements << Type.new(parse_name)
119
+ while @tokens.peek[0] == :+
120
+ expect :+
121
+ implements << Type.new(parse_name)
122
+ end
123
+ end
124
+
125
+ Generic.new(name, implements)
126
+ end
127
+
128
+ FUNC_NAME = %r{
129
+ (
130
+ [a-z][A-Za-z0-9_-]*[!?=]?
131
+ | === | ==
132
+ | \<=\>
133
+ | << | >>
134
+ | <= | >=
135
+ | \-
136
+ | \* | \/
137
+ | % | & | \|
138
+ | \[\]
139
+ | \^
140
+ )
141
+ }x.freeze
142
+
143
+ def scan_single
144
+ case
145
+ when @scanner.scan(/[A-Z][A-Za-z0-9_-]*/)
146
+ [:MNAME, @scanner[0]]
147
+ when @scanner.scan(FUNC_NAME)
148
+ [:FNAME, @scanner[0]]
149
+ when @scanner.scan(/::/) then [:"::"]
150
+ when @scanner.scan(/</) then [:<]
151
+ when @scanner.scan(/>/) then [:>]
152
+ when @scanner.scan(/,/) then [:","]
153
+ when @scanner.scan(/:/) then [:":"]
154
+ when @scanner.scan(/\+/) then [:+]
155
+ when @scanner.scan(/\./) then [:"."]
156
+ when @scanner.scan(/\(/) then [:"("]
157
+ when @scanner.scan(/\)/) then [:")"]
158
+ when @scanner.scan(/\s+/)
159
+ else error([], @string[@scanner.pos])
160
+ end
161
+ end
162
+
163
+ def error(expected, given)
164
+ fail ArgumentError,
165
+ "Unexpected #{given.inspect}, " \
166
+ "expected #{expected.map(&:inspect).join(', ')} " \
167
+ "(source #{@string})"
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end