# encoding: utf-8 # frozen_string_literal: true module Carbon module Compiler module Visitor class Generation module Struct Generation.on Node::Definition::Struct => :visit_struct def visit_struct(node) @index.define(struct: @name) do |struct| struct[:elements] = node.each end struct_accessors(node) struct_allocate(node) end private def struct_allocate(node) fname = @name.call(:allocate, node.map(&:type)) @index.define(function: fname) do |function| function[:return] = @name struct_allocate_params_definition(node, function[:definition]) end fname = @name.call(:allocate, []) @index.define(function: fname) do |function| function[:return] = @name struct_allocate_null_definition(node, function[:definition]) end end def struct_accessors(node) node.each_with_index do |element, index| struct_read_accessor(element, index, node) struct_write_accessor(element, index, node) end end def struct_read_accessor(element, index, node) fname = @name.call(element.name.value, [@name]) @index.define(function: fname) do |function| function[:return] = element.type struct_read_accessor_definition(function[:definition], element, index) end fname = @name.call("@#{element.name.value}", [@name]) @index.define(function: fname) do |function| function[:return] = element.type struct_read_accessor_definition(function[:definition], element, index) end end def struct_write_accessor(element, index, node) pname = @name.to_pointer fname = @name.call("#{element.name.value}=", [pname, element.type]) @index.define(function: fname) do |function| function[:return] = element.type struct_write_accessor_definition(function[:definition], element, index) end fname = @name.call("@#{element.name.value}=", [pname, element.type]) @index.define(function: fname) do |function| function[:return] = element.type struct_write_accessor_definition(function[:definition], element, index) end end def struct_read_accessor_definition(definition, element, index) entry = definition.add("entry").build this = definition.params[0] this.name = "self" entry.ret(entry.extract_value(this, index).as(element.type)) end def struct_write_accessor_definition(definition, element, index) entry = definition.add("entry").build this, value = definition.params this.name, value.name = %w(self value) gep = entry.struct_gep(this, index).as(this.type) entry.store(value, gep) entry.ret(value) end def struct_allocate_params_definition(node, definition) entry = definition.add("entry").build node.each_with_index do |e, i| definition.params[i].name = e.name.value end blank = entry.null(@name).as(@name) definition.params.each_with_index do |param, i| entry.insert_value(blank, param, i) end entry.ret(blank) end def struct_allocate_null_definition(node, definition) entry = definition.add("entry").build entry.ret(entry.null(@name).as(@name)) end end end end end end