$print 'proc tests starting...'

// "hi" // just to internalize this string

var f proc {a} {
    assert 0 === refcount undefined
    assert 1 === refcount print
    assert 0 === refcount ""
    // $print 'refcount a =' refcount a
    // $print refcount "hi" // why 3?
    //assert 2 === refcount "hi" /* only true when using internalizing strings. */
    //throw "hi"
}


eval {
    set f2 f
    assert f2 === f
    assert f2 == f
    unset f2
    assert 'undefined' === typename f2
}

scope {
    var i 0, max 5
    while {i<max} {
        $f i
        set i i+1
    }
    assert max === i
}
assert 'undefined' === typename i

var f2 = scope { return scope { return scope {
    // Demonstrates bubbling up of return value...
    var x proc {a1, a2, a3} { return a1 }
    return x
    throw "NOT REACHED"
}}}

assert 'function' ===  typename f2
assert 1 === [f2 1]
$print 'f2 =' f2




scope {
    var f2 proc {a,b,c} {}
    $f2 // call it once to initialize some internals
    set f3 = get 'f2'
    set key null /*relies on internal details!*/
    assert f3 === f2
    $print 'get "f3" =' get "f3"
    var a2 = get f3 key
    assert 'array' === typename a2
    set a2.3 "yo"
    $print 'magic internal details:' get (get {f3}) key
    unset a2.3
    $print 'magic internal details:' get (get {f3}) key

    set f3.me "you"
    assert "you" === f3.me
    assert "undefined" === typename get f3.("mex")
}

scope {
    var ar array [1,2,3]
    set ar.1 "hi!"
    $print 'ar =' ar
    set ar.3 ar // can no longer be printed out due to cycles
    assert ar.3 // seems to work, but...
    // typename ar.3 // BUG: causes endless loop somewhere
    // assert 'array' === typename ar.3 // BUG: causes endless loop somewhere
}

[print {proc assertions completed.}]
return "end of script #6"
