# encoding: utf-8 # frozen_string_literal: true module Carbon module Compiler module Visitor class Preparation module Function Preparation.on Node::Definition::Function => :visit_function def visit_function(node) params = node.parameters.map { |c| accept(c) } generics = node.generics.map { |c| accept(c) } ptypes = params.map { |c| c.name.value == "self" ? @name : c.type } name = @name.call(node.name, ptypes, generics) error_function_duplicate(node, name) if @_funcs.key?(name) @_funcs[name] = node fname = node._name.merge(generics: generics) body = accept(node.body) node.merge(parameters: params, _name: fname, body: body) end Preparation.on Node::Definition::Function::Parameter => :visit_function_parameter def visit_function_parameter(node) return node if node.name.value == "self" type = accept(node.type) node.merge(type: type) end Preparation.on Concrete::Type::Generic => :visit_function_generic def visit_function_generic(node) name = accept(node.name) implements = node.implements.map { |i| accept(i) } Concrete::Type::Generic.new(name, implements) end Preparation.on Node::Definition::Function::Body => :visit_function_body def visit_function_body(node) node.map! { |c| accept(c) } end private def error_function_duplicate(node, name) @file.emit("Function/Duplicate", node.location) @file.emit("Trace/Location", @_funcs[name].location, "previous function location") end end end end end end