carbon-core 0.1.0

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