# encoding: utf-8 # frozen_string_literal: true require "carbon/concrete/item/struct/element" module Carbon module Concrete module Item # A struct data type. This is normally a sequence of elements that are # stored sequentially in memory. Each element has a name, to reference # which position, and a type. # # @api private # @note # **This class is frozen upon initialization.** This means that any # attempt to modify it will result in an error. In most cases, the # attributes on this class will also be frozen, as well. class Struct include Data # (see Item::Base.from) def self.from(type) { type: type, implements: [], elements: [] } end # Initialize the struct with the given data. # # @param data [::Hash] The data to initialize with. # @option data [Type] :module The name of the struct. # @option data [<::String, Type>] :elements The elements of # the struct. # @option data [] :implements The traits that this # data type implements. def initialize(data) @type = data.fetch(:type) @generics = @type.generics @name = @type.to_s @extern = data[:extern] @implements = Set.new(data.fetch(:implements)) @dependencies = Set.new derive_elements(data.fetch(:elements)) derive_dependencies deep_freeze! end # (see Base#call) def call(build, generics) full = @type.sub(generics) elements = @elements.map(&:type).map { |t| t.sub(generics) } .map { |t| build.fetch(t).last } name = @extern || full.to_s build.items[full] = [self, ::LLVM::Type.struct(elements, false, name)] end private def derive_elements(elements) @elements = elements.map { |e| Element.new(*e) } end def derive_dependencies @dependencies.merge(@elements.map(&:type)) end end end end end