process_defn (TypeChecker)

    # 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