# File lib/type_checker.rb, line 439
  def process_defn(exp)
    name = exp.shift
    unprocessed_args = exp.shift
    args = body = function_type = nil

    @env.scope do
      args = process unprocessed_args

      begin
        body = process exp.shift
      rescue TypeError => err
        puts "Error in method #{name}, trying to unify, whole body blew out"
        raise
      end

      # Function might already have been defined by a :call node.
      # TODO: figure out the receiver type? Is that possible at this stage?
      function_type = Type.function Type.unknown, args.sexp_types, Type.unknown
      @functions.unify(name, function_type) do
        @functions.add_function(name, function_type)
        $stderr.puts "\nWARNING: Registering function #{name}: #{function_type.inspect}" if $DEBUG

      end
    end

    return_type = function_type.list_type.return_type

    # Drill down and find all return calls, unify each one against the
    # registered function return value. That way they all have to
    # return the same type. If we don't end up finding any returns,
    # set the function return type to void.

    return_count = 0
    body.each_of_type(:return) do |sub_exp|
      begin
        return_type.unify sub_exp[1].sexp_type
        return_count += 1
      rescue TypeError => err
        puts "Error in method #{name}, trying to unify #{sub_exp.inspect} against #{return_type.inspect}"
        raise
      end
    end
    if return_count == 0 then
      begin
        return_type.unify Type.void
      rescue TypeError => err
        puts "Error in method #{name}, trying to unify #{function_type.inspect} against Type.void"
        raise
      end
    end

    # TODO: bad API, clean
    raise "wrong" if
      args.sexp_types.size != function_type.list_type.formal_types.size
    args.sexp_types.each_with_index do |type, i|
      type.unify function_type.list_type.formal_types[i]
    end

    return t(:defn, name, args, body, function_type)
  end