# ------------------------------------------------------------------
#  Array procedures - using arrays turns out to be much more efficient
#  than using lists.
# ------------------------------------------------------------------

proc ainsert {dest start src} {
    upvar $dest d
    upvar $src s

    set dlen [array size d]
    set slen [array size s]
    set end [expr $start+$slen]

    for {set i [expr $dlen+$slen-1]; set j [expr $dlen-1] } \
        {$i >= $end} \
        {incr i -1 ; incr j -1 } {
	    set d($i) $d($j)
    }

    for {set i $start ; set j 0 } {$i < $end} {incr i ; incr j} {
	set d($i) $s($j)
    }
}

proc areplace {dest first last {src ""}} {
    upvar $dest d
    set dlen [array size d]

    if {$last >= $dlen} {
	error "\"last\" parameter is out of range in areplace: last=$last length=$dlen"
    }

    if {$src != ""} {
	upvar $src s
	set slen [array size s]
    } else {
	set slen 0
    }

    set shift [expr $slen - ($last - $first + 1)]

    if { $shift > 0 } {
	set end [expr $last+$shift+1]
	for {set i [expr $dlen+$shift-1] ; set j [expr $dlen-1] } \
	    {$i >= $end} \
	    {incr i -1 ; incr j -1 } {
		set d($i) $d($j)
	}
    } else {
	set end [expr $dlen+$shift-1]
	for {set i [expr $last+$shift+1] ; set j [expr $last+1] } \
	    {$i <= $end} \
	    {incr i ; incr j } {
		set d($i) $d($j)
	}
	incr end
	for {set i $end} {$i<$dlen} {incr i} {
	    unset d($i)
	}
    }

    set end [expr $first + $slen]
    for {set i $first ; set j 0} {$i < $end} {incr i ; incr j} {
	set d($i) $s($j)
    }
}

proc arange {src first last dest} {
    upvar $src s
    upvar $dest d

    for {set i $first ; set j 0} {$i <= $last} {incr i ; incr j} {
	set d($j) $s($i)
    }
}

proc aindex {array val} {
    upvar $array a
    set size [array size a]
    set index -1

    for {set i 0} {$i < $size} {incr i} {
	if {$a($i) == $val} {
	    set index $i
	    break
	}
    }
    return $index
}

# ------------------------------------------------------------------
# "aload" loads a list consisting of key/value pairs
# ------------------------------------------------------------------

proc aload {array {var ""}} {
    if {$var == ""} {
	set command [format {
	    foreach _array_pair [set %s] {
		set [lindex $_array_pair 0] [lindex $_array_pair 1]
	    }
	    unset _array_pair
	} $array]

	uplevel $command
    } else {
	upvar $var v
	foreach elem $array {
	    set v([lindex $elem 0]) [lindex $elem 1]
	}
    }
}
