literal 0.2.0 → 1.0.0.rc1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ab1d4d21286c3cc2a094362e0f1f6a94856738c7ba9a93d285607bb57ce49b5
4
- data.tar.gz: 27c2f4fe6ecbb00fcaeb5faf5b4d13849c3ef8dcc6eec817775f55648fac4847
3
+ metadata.gz: 75c7cc8853143bd8f4ac74b7fc4a5b5d2812bd39c0b4f696a87c2ffc0fb31046
4
+ data.tar.gz: 7781d6362e9ae8f75d0156809f95b0c1f8a37df855356173c9b6f09428419bc0
5
5
  SHA512:
6
- metadata.gz: ef894ddc2c2ee8ca82175d3f833ca0a05f479adf164766c681c4bc165a21840f8431da8c4ee6d4d971b10bf4f37427af40914795f2bdd14855927f818633abb7
7
- data.tar.gz: 806aa654d1670c8842dae039c4e0845dbd1ea304bfabb634aefc0ea79b380889d8e249b3348274d11cc7ac01b173e3c9b468d13d4c44f321ceaa8ac83d5b11ec
6
+ metadata.gz: 6acc2552c11ff3c5f12877b5597f9a6a138bf4901f5fce3801004e286b522c6263fa2454621ac4f5511f553af073d5113d96cd1af1045bc9e44c014c15ab7420
7
+ data.tar.gz: 6f9b205b3343426385185ebd0ea0e04164f6a06f9d42d6cb34c542c8d12a98ab327e274b336fb13d389e7380f5bd79831eb2b508f2d019cd6143658db40f3195
data/README.md CHANGED
@@ -1,158 +1,3 @@
1
1
  # A Literal Ruby Gem [WIP]
2
2
 
3
- ## Types
4
-
5
- Literal uses Ruby-native types. Any method that responds to `===(value)` is considered a type. Note, this is how Ruby’s case statements and pattern matching work. It’s also how `Array#any?` and `Array#all?` work. Essentially all Ruby objects are types and just work the way you’d expect them to. A few examples:
6
-
7
- - On a `Range`, `===(value)` checks if the value is within the range.
8
- - On a `Regexp`, `===(value)` checks if the value matches the pattern.
9
- - On a `Class`, `===(value)` checks if the value is an instance of the class.
10
- - On a `Proc`, `===(value)` calls the proc with the value.
11
- - On a `String`, `===(value)` checks if the value is equal to the string.
12
- - On the class `String`, `===(value)` checks if the value is a string.
13
-
14
- Literal extends this idea with the concept of generics or _parameterised_ types. A generic is a method that returns an object that respond to `===(value)`.
15
-
16
- If we want to check that a given value is an `Array`, we could do this:
17
-
18
- ```ruby
19
- Array === [1, 2, 3]
20
- ```
21
-
22
- But what if we want to check that it’s an Array of Integers? Literal provides a library of special types that can be composed for this purpose. In this case, we can use the type `_Array(Integer)`.
23
-
24
- ```ruby
25
- _Array(Integer) === [1, 2, 3]
26
- ```
27
-
28
- These special types are defined on the `Literal::Types` module. To access them in a class, you can `extend` this module. To access them on an instance, you can `include` the module. If you want to use them globally, you can `extend` the module at the root.
29
-
30
- ```ruby
31
- extend Literal::Types
32
- ```
33
-
34
- This is recommended for applications, but not for libraries, as we don’t want to pollute the global namespace from library code.
35
-
36
- `Literal::Properties`, `Literal::Object`, `Literal::Struct` and `Literal::Data` already extend `Literal::Types`, so you don’t need to extend `Literal::Types` yourself if you’re only using literal types for literal properties.
37
-
38
- ## Properties
39
-
40
- `Literal::Properties` is a mixin that allows you to define the structure of an object. Properties are defined using the `prop` method.
41
-
42
- The first argument is the name of the property as a `Symbol`. The second argument is the _type_ of the property. Remember, the type can be any object that responds to `===(value)`.
43
-
44
- The third argument is optional. You can set this to `:*`, `:**`, `:&`, or `:positional` to change the kind of initializer parameter.
45
-
46
- ```ruby
47
- class Person
48
- extend Literal::Properties
49
-
50
- prop :name, String
51
- prop :age, Integer
52
- end
53
- ```
54
-
55
- You can also use keyword arguments to define _readers_ and _writers_. These can be set to `false`, `:public`, `:protected`, or `:private` and default to `false`.
56
-
57
- ```ruby
58
- class Person
59
- extend Literal::Properties
60
-
61
- prop :name, String, reader: :public
62
- prop :age, Integer, writer: :protected
63
- end
64
- ```
65
-
66
- Properties are required by deafult. To make them optional, set the type to a that responds to `===(nil)` with `true`. `Literal::Types` provides a special types for this purpose. Let’s make the age optional by setting its type to a `_Nilable(Integer)`:
67
-
68
- ```ruby
69
- class Person
70
- extend Literal::Properties
71
-
72
- prop :name, String
73
- prop :age, _Nilable(Integer)
74
- end
75
- ```
76
-
77
- Alternatively, you can give the property a default value. This default value must match the type of the property.
78
-
79
- ```ruby
80
- class Person
81
- extend Literal::Properties
82
-
83
- prop :name, String, default: "John Doe"
84
- prop :age, _Nilable(Integer)
85
- end
86
- ```
87
-
88
- Note, the above example will fail unless you have frozen string literals enabled. (Which, honestly, you should.) Default values must be frozen. If you can’t use a frozen value, you can pass a proc instead.
89
-
90
- ```ruby
91
- class Person
92
- extend Literal::Properties
93
-
94
- prop :name, String, default: -> { "John Doe" }
95
- prop :age, _Nilable(Integer)
96
- end
97
- ```
98
-
99
- The proc will be called to generate the default value.
100
-
101
- You can also pass a block to the `prop` method. This block will be called with the value of the property when it’s set, which is useful for coercion.
102
-
103
- ```ruby
104
- class Person
105
- extend Literal::Properties
106
-
107
- prop :name, String
108
- prop :age, Integer do |value|
109
- value.to_i
110
- end
111
- end
112
- ```
113
-
114
- Coercion takes place prior to type-checking, so you can safely coerce a value to a different type in the block.
115
-
116
- You can use properties that conflict with ruby keywords. Literal will handle everything for you automatically.
117
-
118
- ```ruby
119
- class Person
120
- extend Literal::Properties
121
-
122
- prop :class, String, :positional
123
- prop :end, Integer
124
- end
125
- ```
126
-
127
- If you’d prefer to subclass than extend a module, you can use the `Literal::Object` class instead. `Literal::Object` literally extends `Literal::Properties`.
128
-
129
- ```ruby
130
- class Person < Literal::Object
131
- prop :name, String
132
- prop :age, Integer
133
- end
134
- ```
135
-
136
- ## Structs
137
-
138
- `Literal::Struct` is like `Literal::Object`, but it also provides a few extras.
139
-
140
- Structs implement `==` so you can compare one struct to another. They also implement `hash`. Structs also have public _readers_ and _writers_ by default.
141
-
142
- ```ruby
143
- class Person < Literal::Struct
144
- prop :name, String
145
- prop :age, Integer
146
- end
147
- ```
148
-
149
- ## Data
150
-
151
- `Literal::Data` is like `Literal::Struct`, but you can’t define _writers_. Additionally, objects are _frozen_ after initialization. Additionally any non-frozen properties are duplicated and frozen.
152
-
153
- ```ruby
154
- class Person < Literal::Data
155
- prop :name, String
156
- prop :age, Integer
157
- end
158
- ```
3
+ See the website for [documentation](https://literal.fun/docs).
@@ -10,25 +10,18 @@ class Literal::DataStructure
10
10
  object
11
11
  end
12
12
 
13
- def ==(other)
14
- if Literal::DataStructure === other
15
- to_h == other.to_h
16
- else
17
- false
18
- end
19
- end
20
-
21
- def hash
22
- [self.class, to_h].hash
23
- end
24
-
25
13
  def [](key)
26
- instance_variable_get("@#{key}")
14
+ instance_variable_get(:"@#{key}")
27
15
  end
28
16
 
29
17
  def []=(key, value)
30
- @literal_properties[key].check(value)
31
- instance_variable_set("@#{key}", value)
18
+ # TODO: Sync error array w/ generated setter
19
+ @literal_properties[key].check(value) { |c| raise NotImplementedError }
20
+ instance_variable_set(:"@#{key}", value)
21
+ end
22
+
23
+ def to_h
24
+ {}
32
25
  end
33
26
 
34
27
  def deconstruct
@@ -57,4 +50,20 @@ class Literal::DataStructure
57
50
  def marshal_dump
58
51
  [1, to_h, frozen?]
59
52
  end
53
+
54
+ def hash
55
+ self.class.hash
56
+ end
57
+
58
+ def ==(other)
59
+ other.is_a?(self.class) && other.class.literal_properties.empty?
60
+ end
61
+ alias eql? ==
62
+
63
+ def self.__generate_literal_methods__(new_property, buffer = +"")
64
+ super
65
+ literal_properties.generate_hash(buffer)
66
+ literal_properties.generate_eq(buffer)
67
+ buffer
68
+ end
60
69
  end
data/lib/literal/enum.rb CHANGED
@@ -21,6 +21,15 @@ class Literal::Enum
21
21
  @indexes = {}
22
22
  @index = {}
23
23
  end
24
+
25
+ if RUBY_ENGINE != "truffleruby"
26
+ TracePoint.trace(:end) do |tp|
27
+ if tp.self == subclass
28
+ tp.self.__after_defined__
29
+ tp.disable
30
+ end
31
+ end
32
+ end
24
33
  end
25
34
 
26
35
  def index(name, type, unique: true, &block)
@@ -34,9 +43,9 @@ class Literal::Enum
34
43
 
35
44
  key, value = kwargs.first
36
45
 
37
- unless (type = @indexes.fetch(key)[0]) === value
38
- raise Literal::TypeError.expected(value, to_be_a: type)
39
- end
46
+ types = @indexes.fetch(key)
47
+ type = types.first
48
+ Literal.check(actual: value, expected: type) { |c| raise NotImplementedError }
40
49
 
41
50
  @index.fetch(key)[value]
42
51
  end
@@ -76,9 +85,9 @@ class Literal::Enum
76
85
  end
77
86
  end
78
87
 
79
- def new(*, **, &block)
88
+ def new(*args, **kwargs, &block)
80
89
  raise ArgumentError if frozen?
81
- new_object = super(*, **, &nil)
90
+ new_object = super(*args, **kwargs, &nil)
82
91
 
83
92
  if block
84
93
  new_object.instance_exec(&block)
@@ -90,6 +99,10 @@ class Literal::Enum
90
99
  def __after_defined__
91
100
  raise ArgumentError if frozen?
92
101
 
102
+ if RUBY_VERSION < "3.2"
103
+ constants(false).each { |name| const_added(name) }
104
+ end
105
+
93
106
  @indexes.each do |name, (type, unique, block)|
94
107
  index = @members.group_by(&block).freeze
95
108
 
@@ -111,8 +124,8 @@ class Literal::Enum
111
124
  freeze
112
125
  end
113
126
 
114
- def each(&)
115
- @members.each(&)
127
+ def each
128
+ @members.each { |member| yield(member) }
116
129
  end
117
130
 
118
131
  def each_value(&)
@@ -166,11 +179,3 @@ class Literal::Enum
166
179
  Marshal.dump(@value)
167
180
  end
168
181
  end
169
-
170
- TracePoint.trace(:end) do |tp|
171
- it = tp.self
172
-
173
- if Class === it && it < Literal::Enum
174
- it.__after_defined__
175
- end
176
- end
@@ -1,10 +1,83 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Literal::TypeError < TypeError
4
+ INDENT = " "
5
+
4
6
  include Literal::Error
5
7
 
6
- def self.expected(value, to_be_a:)
7
- type = to_be_a
8
- new("Expected `#{value.inspect}` to be of type: `#{type.inspect}`.")
8
+ class Context
9
+ attr_reader :receiver, :method, :label, :expected, :actual, :children
10
+
11
+ def initialize(
12
+ receiver: nil, # _Nilable(Object)
13
+ method: nil, # _Nilable(String)
14
+ label: nil, # _Nilable(String)
15
+ expected: nil, # _Nilable(_Any)
16
+ actual: nil, # _Nilable(_Any)
17
+ parent: nil # _Nilable(Context)
18
+ )
19
+ @receiver = receiver
20
+ @method = method
21
+ @label = label
22
+ @expected = expected
23
+ @actual = actual
24
+ @children = []
25
+ end
26
+
27
+ def descend(level = 0, &blk)
28
+ yield self, level
29
+ @children.each { |child| child.descend(level + 1, &blk) }
30
+ nil
31
+ end
32
+
33
+ def fill_receiver(receiver:, method:, label: nil)
34
+ @receiver = receiver
35
+ @method = method
36
+ @label = label
37
+ end
38
+
39
+ def add_child(expected: nil, **kwargs)
40
+ child = self.class.new(expected:, **kwargs)
41
+ expected.record_literal_type_errors(child) if expected.respond_to?(:record_literal_type_errors)
42
+ @children << child
43
+ end
44
+ end
45
+
46
+ def initialize(context:)
47
+ @context = context
48
+
49
+ super()
50
+ end
51
+
52
+ def message
53
+ message = +"Type mismatch\n\n"
54
+
55
+ @context.descend do |c, level|
56
+ idt = INDENT * level
57
+ if c.receiver || c.method
58
+ message << idt
59
+ message << c.receiver.class.inspect if c.receiver
60
+ message << c.method if c.method
61
+ message << " (from #{backtrace[1]})" if level.zero?
62
+ message << "\n"
63
+ end
64
+ if c.label
65
+ idt << INDENT
66
+ message << idt << c.label << "\n"
67
+ end
68
+ if c.expected && c.children.empty?
69
+ message << idt << " Expected: #{c.expected.inspect}\n"
70
+ message << idt << " Actual (#{c.actual.class}): #{c.actual.inspect}\n"
71
+ end
72
+ end
73
+ message
74
+ end
75
+
76
+ def deconstruct_keys(keys)
77
+ to_h.slice(*keys)
78
+ end
79
+
80
+ def to_h
81
+ @context.to_h
9
82
  end
10
83
  end
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Literal::Properties::DataSchema < Literal::Properties::Schema
4
- def generate_initializer_body(buffer = +"")
5
- buffer << "properties = self.class.literal_properties.properties_index\n"
6
- generate_initializer_handle_properties(@sorted_properties, buffer)
7
- buffer << "after_initialize if respond_to?(:after_initialize)\nfreeze\n"
4
+ def generate_after_initializer(buffer = +"")
5
+ super
6
+ buffer << " freeze\n"
8
7
  end
9
8
  end
@@ -19,7 +19,9 @@ class Literal::Properties::Schema
19
19
  def <<(value)
20
20
  @mutex.synchronize do
21
21
  @properties_index[value.name] = value
22
- @sorted_properties = @properties_index.values.sort!
22
+ # ruby's sort is unstable, this trick makes it stable
23
+ n = 0
24
+ @sorted_properties = @properties_index.values.sort_by! { |it| n += 1; [it, n] }
23
25
  end
24
26
 
25
27
  self
@@ -40,24 +42,71 @@ class Literal::Properties::Schema
40
42
  @sorted_properties.size
41
43
  end
42
44
 
45
+ def empty?
46
+ @sorted_properties.empty?
47
+ end
48
+
43
49
  def generate_initializer(buffer = +"")
50
+ buffer << "alias initialize initialize\n"
44
51
  buffer << "def initialize(#{generate_initializer_params})\n"
45
52
  generate_initializer_body(buffer)
53
+ buffer << "" \
54
+ "rescue Literal::TypeError => error\n" \
55
+ " error.set_backtrace(caller(2))\n" \
56
+ " raise\n" \
57
+ "else\n"
58
+ generate_after_initializer(buffer)
46
59
  buffer << "end\n"
47
60
  end
48
61
 
62
+ def generate_after_initializer(buffer = +"")
63
+ buffer << " after_initialize if respond_to?(:after_initialize)\n"
64
+ end
65
+
49
66
  def generate_to_h(buffer = +"")
50
- buffer << "def to_h\n" << "{\n"
67
+ buffer << "alias to_h to_h\n"
68
+ buffer << "def to_h\n" << " {\n"
51
69
 
52
70
  sorted_properties = @sorted_properties
53
71
  i, n = 0, sorted_properties.size
54
72
  while i < n
55
73
  property = sorted_properties[i]
56
- buffer << property.name.name << ": @" << property.name.name << ",\n"
74
+ buffer << " " << property.name.name << ": @" << property.name.name << ",\n"
57
75
  i += 1
58
76
  end
59
77
 
60
- buffer << "}\n" << "end\n"
78
+ buffer << " }\n" << "end\n"
79
+ end
80
+
81
+ def generate_hash(buffer = +"")
82
+ buffer << "def hash\n [self.class,\n"
83
+
84
+ sorted_properties = @sorted_properties
85
+ i, n = 0, sorted_properties.size
86
+ while i < n
87
+ property = sorted_properties[i]
88
+ buffer << " @" << property.name.name << ",\n"
89
+ i += 1
90
+ end
91
+
92
+ buffer << " ].hash\n" << "end\n"
93
+ end
94
+
95
+ def generate_eq(buffer = +"")
96
+ buffer << "def ==(other)\n"
97
+ buffer << " return false unless other.is_a?(self.class) && other.class.literal_properties.size == self.class.literal_properties.size\n"
98
+
99
+ sorted_properties = @sorted_properties
100
+ i, n = 0, sorted_properties.size
101
+ while i < n
102
+ property = sorted_properties[i]
103
+ buffer << " @" << property.name.name << " == other.#{property.escaped_name}"
104
+ buffer << " &&\n " if i < n - 1
105
+ i += 1
106
+ end
107
+ buffer << " true" if n.zero?
108
+ buffer << "\nend\n"
109
+ buffer << "alias eql? ==\n"
61
110
  end
62
111
 
63
112
  private
@@ -83,7 +132,7 @@ class Literal::Properties::Schema
83
132
  else # required
84
133
  buffer << property.escaped_name
85
134
  end
86
- else # keyword
135
+ when :keyword
87
136
  if property.default?
88
137
  buffer << property.name.name << ": Literal::Null"
89
138
  elsif property.type === nil
@@ -91,6 +140,8 @@ class Literal::Properties::Schema
91
140
  else # required
92
141
  buffer << property.name.name << ":"
93
142
  end
143
+ else
144
+ raise "You should never see this error."
94
145
  end
95
146
 
96
147
  i += 1
@@ -101,9 +152,8 @@ class Literal::Properties::Schema
101
152
  end
102
153
 
103
154
  def generate_initializer_body(buffer = +"")
104
- buffer << "properties = self.class.literal_properties.properties_index\n"
155
+ buffer << " properties = self.class.literal_properties.properties_index\n"
105
156
  generate_initializer_handle_properties(@sorted_properties, buffer)
106
- buffer << "after_initialize if respond_to?(:after_initialize)\n"
107
157
  end
108
158
 
109
159
  def generate_initializer_handle_properties(properties, buffer = +"")
@@ -6,6 +6,11 @@ module Literal::Properties
6
6
 
7
7
  include Literal::Types
8
8
 
9
+ def self.extended(base)
10
+ super
11
+ base.include(base.__send__(:__literal_extension__))
12
+ end
13
+
9
14
  def prop(name, type, kind = :keyword, reader: false, writer: false, predicate: false, default: nil, &coercion)
10
15
  if default && !(Proc === default || default.frozen?)
11
16
  raise Literal::ArgumentError.new("The default must be a frozen object or a Proc.")
@@ -66,16 +71,25 @@ module Literal::Properties
66
71
  end
67
72
 
68
73
  def __define_literal_methods__(new_property)
69
- __literal_extension__.module_eval(
70
- __generate_literal_methods__(new_property),
71
- )
74
+ code = __generate_literal_methods__(new_property)
75
+ __literal_extension__.module_eval(code)
72
76
  end
73
77
 
74
78
  def __literal_extension__
75
79
  if defined?(@__literal_extension__)
76
80
  @__literal_extension__
77
81
  else
78
- @__literal_extension__ = Module.new
82
+ @__literal_extension__ = Module.new do
83
+ def initialize
84
+ after_initialize if respond_to?(:after_initialize)
85
+ end
86
+
87
+ def to_h
88
+ {}
89
+ end
90
+
91
+ set_temporary_name "Literal::Properties(Extension)" if respond_to?(:set_temporary_name)
92
+ end
79
93
  end
80
94
  end
81
95
 
@@ -51,7 +51,24 @@ class Literal::Property
51
51
  end
52
52
 
53
53
  def default?
54
- nil != @default
54
+ nil != @default
55
+ end
56
+
57
+ def param
58
+ case @kind
59
+ when :*
60
+ "*#{escaped_name}"
61
+ when :**
62
+ "**#{escaped_name}"
63
+ when :&
64
+ "&#{escaped_name}"
65
+ when :positional
66
+ escaped_name
67
+ when :keyword
68
+ "#{@name.name}:"
69
+ else
70
+ raise "You should never see this error."
71
+ end
55
72
  end
56
73
 
57
74
  def <=>(other)
@@ -77,18 +94,28 @@ class Literal::Property
77
94
  end
78
95
  end
79
96
 
80
- def check(value)
81
- Literal.check(value, @type)
97
+ def check(value, &)
98
+ raise ArgumentError.new("Cannot check type without a block") unless block_given?
99
+
100
+ Literal.check(actual: value, expected: @type, &)
101
+ end
102
+
103
+ def check_writer(receiver, value)
104
+ Literal.check(actual: value, expected: @type) { |c| c.fill_receiver(receiver:, method: "##{@name.name}=(value)") }
105
+ end
106
+
107
+ def check_initializer(receiver, value)
108
+ Literal.check(actual: value, expected: @type) { |c| c.fill_receiver(receiver:, method: "#initialize", label: param) }
82
109
  end
83
110
 
84
111
  def generate_reader_method(buffer = +"")
85
112
  buffer <<
86
113
  (@reader ? @reader.name : "public") <<
87
- " def " <<
114
+ "\ndef " <<
88
115
  @name.name <<
89
- "\nvalue = @" <<
116
+ "\n value = @" <<
90
117
  @name.name <<
91
- "\nvalue\nend\n"
118
+ "\n value\nend\n"
92
119
  end
93
120
 
94
121
  if Literal::TYPE_CHECKS_DISABLED
@@ -98,7 +125,7 @@ class Literal::Property
98
125
  " def " <<
99
126
  @name.name <<
100
127
  "=(value)\n" <<
101
- "@#{@name.name} = value\nend\n"
128
+ " @#{@name.name} = value\nend\n"
102
129
  end
103
130
  else # type checks are enabled
104
131
  def generate_writer_method(buffer = +"")
@@ -107,10 +134,12 @@ class Literal::Property
107
134
  " def " <<
108
135
  @name.name <<
109
136
  "=(value)\n" <<
110
- "self.class.literal_properties[:" <<
137
+ " self.class.literal_properties[:" <<
111
138
  @name.name <<
112
- "].check(value)\n" <<
113
- "@#{@name.name} = value\nend\n"
139
+ "].check_writer(self, value)\n" <<
140
+ " @" << @name.name << " = value\n" <<
141
+ "rescue Literal::TypeError => error\n error.set_backtrace(caller(1))\n raise\n" <<
142
+ "end\n"
114
143
  end
115
144
  end
116
145
 
@@ -120,15 +149,15 @@ class Literal::Property
120
149
  " def " <<
121
150
  @name.name <<
122
151
  "?\n" <<
123
- "!!@" <<
152
+ " !!@" <<
124
153
  @name.name <<
125
154
  "\n" <<
126
155
  "end\n"
127
156
  end
128
157
 
129
158
  def generate_initializer_handle_property(buffer = +"")
130
- buffer << "# " << @name.name << "\n" <<
131
- "property = properties[:" << @name.name << "]\n"
159
+ buffer << " # " << @name.name << "\n" <<
160
+ " property = properties[:" << @name.name << "]\n"
132
161
 
133
162
  if @kind == :keyword && ruby_keyword?
134
163
  generate_initializer_escape_keyword(buffer)
@@ -169,25 +198,23 @@ class Literal::Property
169
198
 
170
199
  def generate_initializer_assign_default(buffer = +"")
171
200
  buffer <<
172
- "if " <<
201
+ " if " <<
173
202
  ((@kind == :&) ? "nil" : "Literal::Null") <<
174
203
  " == " <<
175
204
  escaped_name <<
176
- "\n" <<
205
+ "\n " <<
177
206
  escaped_name <<
178
- " = property.default_value\nend\n"
207
+ " = property.default_value\n end\n"
179
208
  end
180
209
 
181
210
  def generate_initializer_check_type(buffer = +"")
182
211
  buffer <<
183
- "unless property.type === " << escaped_name << "\n" <<
184
- "raise Literal::TypeError.expected(" << escaped_name << ", to_be_a: property.type)\n" <<
185
- "end\n"
212
+ " property.check_initializer(self, " << escaped_name << ")\n"
186
213
  end
187
214
 
188
215
  def generate_initializer_assign_value(buffer = +"")
189
216
  buffer <<
190
- "@" <<
217
+ " @" <<
191
218
  @name.name <<
192
219
  " = " <<
193
220
  escaped_name <<