# encoding: utf-8 # frozen_string_literal: true require "carbon/compiler/node/etype/option" require "carbon/compiler/node/etype/star" module Carbon module Compiler module Node class EType < Base def expand(file, typify = true) catch(:invalid) { check_valid_parts(file) } or return {} return blank_mapping if clean? # now we know that children[0..-2] are all parts and children[-1] is # an option... we just have to expand the option now. children[-1].expand(file).map do |key, value| value = children[0..-2].concat(value) if typify { Concrete::Type.new(Concrete::Type::Name.new([key], nil)) => Concrete::Type.new(Concrete::Type::Name.new(value, nil)) } else { key => value } end end.inject(:merge) end def clean? children.none? { |c| c.is_a?(Base) } end def to_type return unless clean? Concrete::Type.new(Concrete::Type::Name.new(children, nil), location: location) end private def blank_mapping type = Concrete::Type.new(Concrete::Type::Name.new([children.last], nil)) { type => to_type } end def check_valid_parts(file) error_misplaced_option(file) && throw(:invalid) if children[0..-2]\ .any? { |c| c.is_a?(Base) } error_included_star(file) && throw(:invalid) if children[-1]\ .is_a?(EType::Star) true end def error_misplaced_option(file) file.emit("Module/Name/InvalidExtended", node.location) end def error_included_star(file) file.emit("System/Error", node.location, "Cannot handle star extended types") end end end end end