phylanx icon indicating copy to clipboard operation
phylanx copied to clipboard

Calling inner functions with arguments broken

Open hkaiser opened this issue 7 years ago • 7 comments

Calling an inner function with arguments from the same nesting level as it was defined complains about the argument count being out of bounds:

{what}: main_func(3, 35): access-argument$a:: argument count out of bounds, expected at least 2 argument(s) while only 1 argument(s) were supplied: HPX(bad_parameter)

This code exposes the problem:

// Copyright (c) 2018 Adrian Serio
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <phylanx/phylanx.hpp>
#include <hpx/hpx_main.hpp>

int main()
{
    // Test calling an inner function
    char const* const main_code = R"(block(
        define(main_func, x, block(
            define(inner, a, cout(var)),
            inner(x)
        )),
        main_func
    ))";

    phylanx::execution_tree::compiler::function_list snippets;
    phylanx::execution_tree::compiler::environment envir =
        phylanx::execution_tree::compiler::default_environment();

    auto const& code = phylanx::execution_tree::compile(
        "main_func", main_code, snippets, envir);
    auto main_ = code.run();

    auto result = main_(3.0);

    return 0;
}

hkaiser avatar Oct 24 '18 15:10 hkaiser

The following code prints "5". Does that mean this issue is fixed?

from phylanx import Phylanx

@Phylanx
def foo():
    def add(a, b):
        a + b
    add(3, 2)

print(foo())

stevenrbrandt avatar Dec 05 '18 16:12 stevenrbrandt

@stevenrbrandt yes, things are ok if the outer function does not take any function arguments.

hkaiser avatar Dec 05 '18 23:12 hkaiser

This also works

@Phylanx
def foo2():
    def one(a):
        a + 5
    return one(3)

stevenrbrandt avatar Dec 06 '18 18:12 stevenrbrandt

Also, this PhySL code works... which is different from the above (the one above doesn't work because it contains an undefined variable named var):

block(
    define(main_func, x, block(
        define(inner, a, cout(x)),
        inner(x)
    )),
    main_func(3)
)

stevenrbrandt avatar Dec 06 '18 18:12 stevenrbrandt

@stevenrbrandt as said, things work as long as the outer function has no arguments. Also, your last example does not use the inner function's argument, which prevents the error from showing up.

hkaiser avatar Dec 06 '18 18:12 hkaiser

OK, so the relevant physl code is this:

block(
    define(main_func, x, block(
        define(inner, a, cout(a)),
        inner(x)
    )),
    main_func(3)
)

And that fails.

stevenrbrandt avatar Dec 06 '18 20:12 stevenrbrandt

@hkaiser I've done a little more experimenting. Essentially, when the code checks the number of arguments for inner, it's actually looking at the number for main_func (including the block). My guess is the fix for this is very simple if one knows the source code well. Thus

block(
    define(main_func, x, y, block(
        define(inner, a, block(cout(a))),
        inner(x)
    )),
    main_func(3)
)

Wants 3 arguments to inner and

block(
    define(main_func, x, y, block(
        define(inner, a, block(cout(a))),
        inner(x)
    )),
    main_func(3)
)

Wants 4 arguments to inner. Conversely, this code works:

block(
    define(main_func, x, block(
        define(inner, a, b, block(cout(a))),
        inner(x, 1)
    )),
    main_func(3)
)

as does this (even though it shouldn't).

block(
    define(main_func, x, block(
        define(inner, a, b, c, block(cout(a))),
        inner(x, 1)
    )),
    main_func(3)
)

stevenrbrandt avatar Feb 01 '19 20:02 stevenrbrandt