/**
    Experimenting with the @expando operator,
    which expands an array in-place, as if each
    entry of the array were a token. It essentially
    works but has a couple corner cases, mostly
    involving empty arrays. For now it is only
    available in the context of processing
    function arguments and the function being called
    may not be part of the @expando. (Fixing that
    requires larger changes.)

*/

const run = proc{code}{
    [print code]
    scope code
}

0 || scope {
    $print "array av..."
    var av = array["one",2,3.3]
    [av.unshift "four" 5]
    assert 5 === av.1
    assert "four" === av.0
    $run {print(av)} // if you get a parse error here, enable "conventional" func call syntax with -c
    $run {print(@av)}
    $run {[print.apply print av]}
    $run {[print.call print @av]}

    if(catch{@av}){
        print("Generic @expando support disabled.",
              "Skipping those tests")
        return
    }
    const x = array[array[@av],array[@av]]
    assert av.length() === x.(0).length()
    $run {print.call(print, "x =", x)}

    $print "array b..."
    var b = array[@av]
    $run {assert b.length() === av.length()}
    $run {print(b, @b)}

    0 || scope {
        print("One of the empty-array corner cases:");
        var x = array[]
        $run {
            var y = array[@x]
            print('y=',y)
        }
    }


    if(false){
        /* Problemlage: this construct will accidentally
           tell the script it has reached EOF because
           [...] is done as a sub-parse and @b->right
           is EOF in the [...] block, but @ does not
           know that it is in the [] block (the effect
           would happen with other sub-parsed constructs
           as well). We don't have a way to track parse
           levels, so that we can jump back to the previous
           one. Looks like we need one.
        */
        $run {
            b.unshift(print)
            print(b)
            [@b]
        }
        throw "did we reach here?"
        $run {
            b.unshift(print.call, print)
            $print b @b
            //$@b // broken, but that's okay b/c this works:
            [@b]
        }

        $run {
            var x = @b
            assert b.0 === x
            assert x === (@b) // also subject to the EOF behaviour :/
        }
    }
    @b
}

0 || scope {
    print("empty array c...")
    var c = array[]
    //@c 1
    $run {$print @c 2 @c}
    $run {[print @c 2 @c]}
    $run {$print 1 @c 3 @c 5}
    $run {[print 1 @c 3 @c 5]}
    $run {print(1,2,@c)}
    $run {[print 1 2 @c]}
    $run {print(1,2,@c,4)}
    $run {[print 1 2 @c 4]}
}

const rc = "End of @expando tests."
return (print(rc), rc)
