Class: MilkTea::SubstituteTypeVisitor

Inherits:
Object
  • Object
show all
Defined in:
lib/milk_tea/core/types/visitor.rb

Instance Method Summary collapse

Constructor Details

#initialize(substitutions) ⇒ SubstituteTypeVisitor

Returns a new instance of SubstituteTypeVisitor.



268
269
270
# File 'lib/milk_tea/core/types/visitor.rb', line 268

def initialize(substitutions)
  @substitutions = substitutions
end

Instance Method Details

#apply(type) ⇒ Object



272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/milk_tea/core/types/visitor.rb', line 272

def apply(type)
  case type
  when Types::TypeVar
    @substitutions.fetch(type.name, type)
  when Types::LifetimeRef
    @substitutions.fetch(type.name, type)
  when Types::Nullable
    substituted = apply(type.base)
    substituted.equal?(type.base) ? type : Types::Registry.nullable(substituted)
  when Types::GenericInstance
    new_args = type.arguments.map do |arg|
      arg.is_a?(Types::LiteralTypeArg) ? arg : apply(arg)
    end
    type.arguments.zip(new_args).all? { |old, new| old.equal?(new) } ? type : Types::Registry.generic_instance(type.name, new_args)
  when Types::Span
    substituted = apply(type.element_type)
    substituted.equal?(type.element_type) ? type : Types::Registry.span(substituted)
  when Types::Task
    substituted = apply(type.result_type)
    substituted.equal?(type.result_type) ? type : Types::Registry.task(substituted)
  when Types::Event
    new_payload = type.payload_type ? apply(type.payload_type) : nil
    if new_payload.equal?(type.payload_type)
      type
    else
      Types::Event.new(type.name, capacity: type.capacity, payload_type: new_payload, module_name: type.module_name, visibility: type.visibility, owner_type_name: type.owner_type_name)
    end
  when Types::Proc
    changed = false
    new_params = type.params.map do |param|
      new_param_type = apply(param.type)
      new_boundary = param.boundary_type ? apply(param.boundary_type) : nil
      changed = true unless new_param_type.equal?(param.type) && new_boundary.equal?(param.boundary_type)
      Types::Registry.parameter(param.name, new_param_type, mutable: param.mutable, passing_mode: param.passing_mode, boundary_type: new_boundary)
    end
    new_return = apply(type.return_type)
    changed = true unless new_return.equal?(type.return_type)
    changed ? Types::Registry.proc(params: new_params, return_type: new_return) : type
  when Types::Function
    changed = false
    new_params = type.params.map do |param|
      new_param_type = apply(param.type)
      new_boundary = param.boundary_type ? apply(param.boundary_type) : nil
      changed = true unless new_param_type.equal?(param.type) && new_boundary.equal?(param.boundary_type)
      Types::Registry.parameter(param.name, new_param_type, mutable: param.mutable, passing_mode: param.passing_mode, boundary_type: new_boundary)
    end
    new_return = apply(type.return_type)
    changed = true unless new_return.equal?(type.return_type)
    new_receiver = type.receiver_type ? apply(type.receiver_type) : nil
    changed = true unless new_receiver.equal?(type.receiver_type)
    changed ? Types::Registry.function(type.name, params: new_params, return_type: new_return, receiver_type: new_receiver, receiver_editable: type.receiver_editable, variadic: type.variadic, external: type.external) : type
  when Types::StructInstance
    new_args = type.arguments.map { |arg| apply(arg) }
    type.arguments.zip(new_args).all? { |old, new| old.equal?(new) } ? type : type.definition.instantiate(new_args)
  when Types::VariantInstance
    new_args = type.arguments.map { |arg| apply(arg) }
    type.arguments.zip(new_args).all? { |old, new| old.equal?(new) } ? type : type.definition.instantiate(new_args)
  else
    type
  end
end