Repository: STEllAR-GROUP/phylanx (language: python)

Issue:
array primitive doesn't work correctly
One expects the array() primitive to convert a list to vector as it does in numpy. Unfortunately, as you see in the foo() method, it instead produces an error claiming that the list is ir::range and not a numeric type.

There is a workaround. In foo2(), the call to transpose(vstack(li))[0] does what I would expect array(li) to produce. However, this is doubtless less efficient than it ought to be.
```
from phylanx import Phylanx
import numpy as np

@Phylanx
def foo():
    li = [1,2,3,4,5]
    print(li)
    print(array(li))

@Phylanx
def foo2():
    li = [1,2,3,4,5]
    print(li)
    print(transpose(vstack(li))[0])

foo2()
foo()
```
Produces
```
list(1, 2, 3, 4, 5)
[1, 2, 3, 4, 5]
list(1, 2, 3, 4, 5)
Traceback (most recent call last):
  File "x.py", line 17, in <module>
    foo()
  File "/home/jovyan/.local/lib/python3.8/site-packages/phylanx-0.0.1-py3.8-linux-x86_64.egg/phylanx/ast/transducer.py", line 191, in __call__
    result = self.backend.call(*mapped_args, **mapped_kwargs)
  File "/home/jovyan/.local/lib/python3.8/site-packages/phylanx-0.0.1-py3.8-linux-x86_64.egg/phylanx/ast/physl.py", line 597, in call
    result = phylanx.execution_tree.eval(
RuntimeError: x.py(1, 111): hstack:: primitive_argument_type does not hold a numeric value type (type held: 'phylanx::ir::range'): HPX(bad_parameter)
```


Discussion / hints:

Fix patch:
diff --git a/src/plugins/matrixops/stack_operation.cpp b/src/plugins/matrixops/stack_operation.cpp
index f56500ad1..2aa266a1c 100644
--- a/src/plugins/matrixops/stack_operation.cpp
+++ b/src/plugins/matrixops/stack_operation.cpp
@@ -218,8 +218,16 @@ namespace phylanx { namespace execution_tree { namespace primitives
 
         for (std::size_t i = 0; i != args.size(); ++i)
         {
-            std::size_t num_dims =
-                extract_numeric_value_dimension(args[i], name_, codename_);
+            std::size_t num_dims = std::size_t(-1);
+            if (is_list_operand_strict(args[i]))
+            {
+                num_dims = 1;
+            }
+            else if (is_numeric_operand(args[i]))
+            {
+                num_dims =
+                    extract_numeric_value_dimension(args[i], name_, codename_);
+            }
 
             if (num_dims != 0 && num_dims != 1)
             {
@@ -228,13 +236,18 @@ namespace phylanx { namespace execution_tree { namespace primitives
                         "stack_operation::get_vecsize",
                     generate_error_message(
                         "for 0d/1d stacking, the stack_operation primitive "
-                        "requires the input be either a vector or a scalar"));
+                        "requires the input to be either a list, a vector or "
+                        "a scalar"));
             }
 
             if (num_dims == 0)
             {
                 ++vec_size;
             }
+            else if (is_list_operand_strict(args[i]))
+            {
+                vec_size += extract_list_value_size(args[i], name_, codename_);
+            }
             else
             {
                 vec_size += extract_numeric_value_dimensions(
@@ -260,16 +273,30 @@ namespace phylanx { namespace execution_tree { namespace primitives
         auto iter = result.begin();
         for (auto && arg : args)
         {
-            auto && val = extract_node_data<T>(std::move(arg));
-            std::size_t num_d = val.num_dimensions();
-            if (num_d == 0)
+            if (is_list_operand_strict(arg))
             {
-                *iter++ = val.scalar();
+                auto&& val =
+                    extract_list_value_strict(std::move(arg), name_, codename_);
+                for (auto&& v : val)
+                {
+                    *iter++ =
+                        extract_scalar_data<T>(std::move(v), name_, codename_);
+                }
             }
             else
             {
-                std::copy(val.vector().begin(), val.vector().end(), iter);
-                iter += val.size();
+                auto&& val =
+                    extract_node_data<T>(std::move(arg), name_, codename_);
+                std::size_t num_d = val.num_dimensions();
+                if (num_d == 0)
+                {
+                    *iter++ = val.scalar();
+                }
+                else
+                {
+                    iter = std::copy(
+                        val.vector().begin(), val.vector().end(), iter);
+                }
             }
         }
 


Test patch:
diff --git a/tests/regressions/python/1302_array.py b/tests/regressions/python/1302_array.py
new file mode 100644
index 000000000..fb79125df
--- /dev/null
+++ b/tests/regressions/python/1302_array.py
@@ -0,0 +1,19 @@
+#  Copyright (c) 2021 Steven R. Brandt
+#
+#  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)
+
+# #1281: Phylanx Minimum Viable Product
+
+from phylanx import Phylanx
+import numpy as np
+
+
+@Phylanx
+def foo():
+    li = [1, 2, 3, 4, 5]
+    return np.array(li)
+
+
+result = foo()
+assert (result == np.array([1, 2, 3, 4, 5])).all(), result
diff --git a/tests/regressions/python/CMakeLists.txt b/tests/regressions/python/CMakeLists.txt
index 8c53fba02..4dab3708a 100644
--- a/tests/regressions/python/CMakeLists.txt
+++ b/tests/regressions/python/CMakeLists.txt
@@ -69,6 +69,7 @@ set(tests
     1280_hstack_problem
     1281_hostname
     1301_return_tuple
+    1302_array
     1303_iterate_over_array
     array_len_494
     array_shape_486