# ex:ts=8
# vim:sts=4:sw=4:tw=120
#
# Copyright (C) 2003 Eivind Eklund.  All rights reserved.
# See LICENSE.txt for licensing.
#
class Class
    def dullinit(*args, &block)
	header = nil
	body = "super()\n"
	has_rest = false
	while args.length > 0
	    arg = args.shift
	    if args.length == 0 && arg == :rest
		raise ArgumentError, ":rest without block" unless block_given?
		#has_rest = true
		next
		#args = []
	    end
	    if header
		header << ", #{arg}"
	    else
		header = arg.to_s
	    end
	    body << "@#{arg} = #{arg}\n"
	end
	if block_given?
	    @dullinit_block = block
	    larity = block.arity
	    # Hack to work around Ruby giving blocks with no arguments an arity of -1!
	    if larity == 0 || (larity == -1 && !has_rest)
		body << "instance_eval(&(self.class.instance_eval { @dullinit_block }))"
	    else
		# XXX This cannot be done without some way of passing arguments to blocks while changing their binding.
		# I do not know of any way to do this.
		raise RuntimeError, "Multi-arguments to block not supported due to shortcomings in instance_eval"
		if header
		    header << ", arg0"
		else
		    header = "arg0"
		end
		body << "self.class.instance_eval { @dullinit_block }.instance_eval (_dullinit_arg0"
		1.upto(larity-1) { |i|
		    body << ", _dullinit_arg#{i}"
		}
		body << ")"
	    end
	end
	module_eval "def initialize(#{header})\n#{body}\nend"
    end
end
