Skip to content

Commit

Permalink
Merge branch 'devel' of https://github.com/pyccel/pyccel-cuda into is…
Browse files Browse the repository at this point in the history
…sue_56
  • Loading branch information
smazouz42 committed Jul 26, 2024
2 parents eea028a + 12d98b6 commit 09c6b74
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 30 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jobs:
uses: actions/checkout@v4
with:
submodules: true
ref: main
- name: Install dependencies
uses: ./.github/actions/linux_install
- name: Update build
Expand Down
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ All notable changes to this project will be documented in this file.
- #1895 : Add Python support for dict initialisation with `{}`.
- #1895 : Add Python support for dict initialisation with `dict()`.
- #1886 : Add Python support for dict method `pop()`.
- #1944 : Add the appropriate C language equivalent for declaring a Python `dict` container using the STC library.
- #1936 : Add missing C output for inline decorator example in documentation
- #1937 : Optimise `pyccel.ast.basic.PyccelAstNode.substitute` method.
- \[INTERNALS\] Added `container_rank` property to `ast.datatypes.PyccelType` objects.
- \[DEVELOPER\] Added an improved traceback to the developer-mode errors for errors in function calls.

Expand All @@ -60,6 +63,7 @@ All notable changes to this project will be documented in this file.
- #1927 : Improve error Message for missing target language compiler in Pyccel
- #1933 : Improve code printing speed.
- #1930 : Preserve ordering of import targets.
- #1951 : Fix return type for class whose argument cannot be wrapped.

### Changed

Expand Down Expand Up @@ -102,7 +106,7 @@ All notable changes to this project will be documented in this file.
- \[INTERNALS\] Remove unused/unnecessary functions in `pyccel.parser.utilities` : `read_file`, `header_statement`, `accelerator_statement`, `get_module_name`, `view_tree`.
- \[INTERNALS\] Remove unused functions `Errors.unset_target`, and `Errors.reset_target`.

## \[1.12.0\] - 2024-05-08
## \[1.12.0\] - 2024-05-13

### Added

Expand Down
4 changes: 3 additions & 1 deletion docs/builtin-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Python contains a limited number of builtin functions defined [here](https://doc
| `compile` | No |
| **`complex`** | **Yes** |
| `delattr` | No |
| *`dict`* | Preliminary Python support |
| *`dict`* | Preliminary Python and C **unordered** support |
| `dir` | No |
| `divmod` | No |
| **`enumerate`** | as a loop iterable |
Expand Down Expand Up @@ -76,6 +76,8 @@ Python contains a limited number of builtin functions defined [here](https://doc

## Dictionary methods

:warning: The dictionary support provided by Pyccel only covers unordered dictionaries.

| Method | Supported |
|----------|-----------|
| `clear` | No |
Expand Down
30 changes: 30 additions & 0 deletions docs/decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,36 @@ end module boo

The generated C code:
```c
#include "boo.h"


/*........................................*/
int64_t f(int64_t* a, int64_t* b, int64_t* c, int64_t* d)
{
int64_t Dummy_0000;
int64_t Dummy_0001;
int64_t Dummy_0002;
int64_t Dummy_0003;
int64_t Dummy_0004;
int64_t Dummy_0005;
int64_t Dummy_0006;
int64_t Dummy_0007;
Dummy_0000 = INT64_C(2);
Dummy_0001 = INT64_C(4);
(*a) = Dummy_0000 + Dummy_0001;
Dummy_0002 = INT64_C(3);
Dummy_0003 = INT64_C(5);
(*b) = Dummy_0002 + Dummy_0003;
Dummy_0004 = INT64_C(6);
Dummy_0005 = INT64_C(5);
(*c) = Dummy_0004 + Dummy_0005;
Dummy_0006 = INT64_C(3);
Dummy_0007 = INT64_C(4);
(*d) = Dummy_0006 + Dummy_0007;
return 0;
}
/*........................................*/

```
### Import Error when imported from the shared library
Expand Down
5 changes: 5 additions & 0 deletions pyccel/ast/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,11 @@ def substitute(self, original, replacement, excluded_nodes = (), invalidate = Tr
return
self._recursion_in_progress = True

if not original:
assert not replacement
self._recursion_in_progress = False
return

if iterable(original):
assert iterable(replacement)
assert len(original) == len(replacement)
Expand Down
49 changes: 34 additions & 15 deletions pyccel/codegen/printing/ccode.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from pyccel.ast.builtins import PythonRange, PythonComplex
from pyccel.ast.builtins import PythonPrint, PythonType
from pyccel.ast.builtins import PythonList, PythonTuple, PythonSet
from pyccel.ast.builtins import PythonList, PythonTuple, PythonSet, PythonDict

from pyccel.ast.core import Declare, For, CodeBlock
from pyccel.ast.core import FuncAddressDeclare, FunctionCall, FunctionCallArgument
Expand All @@ -29,7 +29,7 @@
from pyccel.ast.datatypes import TupleType, FixedSizeNumericType
from pyccel.ast.datatypes import CustomDataType, StringType, HomogeneousTupleType, HomogeneousListType, HomogeneousSetType
from pyccel.ast.datatypes import PrimitiveBooleanType, PrimitiveIntegerType, PrimitiveFloatingPointType, PrimitiveComplexType
from pyccel.ast.datatypes import HomogeneousContainerType
from pyccel.ast.datatypes import HomogeneousContainerType, DictType

from pyccel.ast.internals import Slice, PrecomputedCode, PyccelArrayShapeElement

Expand Down Expand Up @@ -682,8 +682,13 @@ def init_stc_container(self, expr, assignment_var):
The generated C code for the container initialization.
"""

dtype = self.get_c_type(assignment_var.lhs.class_type)
keyraw = '{' + ', '.join(self._print(a) for a in expr.args) + '}'
class_type = assignment_var.lhs.class_type
dtype = self.get_c_type(class_type)
if isinstance(expr, PythonDict):
dict_item_strs = [(self._print(k), self._print(v)) for k,v in zip(expr.keys, expr.values)]
keyraw = '{' + ', '.join(f'{{{k}, {v}}}' for k,v in dict_item_strs) + '}'
else:
keyraw = '{' + ', '.join(self._print(a) for a in expr.args) + '}'
container_name = self._print(assignment_var.lhs)
init = f'{container_name} = c_init({dtype}, {keyraw});\n'
return init
Expand Down Expand Up @@ -1017,15 +1022,22 @@ def _print_Import(self, expr):
for t in expr.target:
dtype = t.object.class_type
container_type = t.target
container_key = self.get_c_type(dtype.element_type)
if isinstance(dtype, DictType):
container_key_key = self.get_c_type(dtype.key_type)
container_val_key = self.get_c_type(dtype.value_type)
container_key = f'{container_key_key}_{container_val_key}'
element_decl = f'#define i_key {container_key_key}\n#define i_val {container_val_key}\n'
else:
container_key = self.get_c_type(dtype.element_type)
element_decl = f'#define i_key {container_key}\n'
header_guard_prefix = import_header_guard_prefix.get(source, '')
header_guard = f'{header_guard_prefix}_{container_type.upper()}'
code += (f'#ifndef {header_guard}\n'
f'#define {header_guard}\n'
f'#define i_type {container_type}\n'
f'#define i_key {container_key}\n'
f'#include <{source}.h>\n'
f'#endif // {header_guard}\n\n')
code += ''.join((f'#ifndef {header_guard}\n',
f'#define {header_guard}\n',
f'#define i_type {container_type}\n',
element_decl,
f'#include <{source}.h>\n',
f'#endif // {header_guard}\n\n'))
return code
# Get with a default value is not used here as it is
# slower and on most occasions the import will not be in the
Expand Down Expand Up @@ -1249,6 +1261,13 @@ def get_c_type(self, dtype):
i_type = f'{container_type}_{element_type}'
self.add_import(Import(f'stc/{container_type}', AsName(VariableTypeAnnotation(dtype), i_type)))
return i_type
elif isinstance(dtype, DictType):
container_type = 'hmap'
key_type = self.get_c_type(dtype.key_type).replace(' ', '_')
val_type = self.get_c_type(dtype.value_type).replace(' ', '_')
i_type = f'{container_type}_{key_type}_{val_type}'
self.add_import(Import(f'stc/{container_type}', AsName(VariableTypeAnnotation(dtype), i_type)))
return i_type
else:
key = dtype

Expand Down Expand Up @@ -1325,7 +1344,7 @@ def get_declare_type(self, expr):
rank = expr.rank

if rank > 0:
if isinstance(expr.class_type, (HomogeneousSetType, HomogeneousListType)):
if isinstance(expr.class_type, (HomogeneousSetType, HomogeneousListType, DictType)):
dtype = self.get_c_type(expr.class_type)
return dtype
if isinstance(expr.class_type,(HomogeneousTupleType, NumpyNDArrayType)):
Expand Down Expand Up @@ -1620,7 +1639,7 @@ def _print_PyccelArrayShapeElement(self, expr):
def _print_Allocate(self, expr):
free_code = ''
variable = expr.variable
if isinstance(variable.class_type, (HomogeneousListType, HomogeneousSetType)):
if isinstance(variable.class_type, (HomogeneousListType, HomogeneousSetType, DictType)):
return ''
if variable.rank > 0:
#free the array if its already allocated and checking if its not null if the status is unknown
Expand Down Expand Up @@ -1656,7 +1675,7 @@ def _print_Allocate(self, expr):
raise NotImplementedError(f"Allocate not implemented for {variable}")

def _print_Deallocate(self, expr):
if isinstance(expr.variable.class_type, (HomogeneousListType, HomogeneousSetType)):
if isinstance(expr.variable.class_type, (HomogeneousListType, HomogeneousSetType, DictType)):
variable_address = self._print(ObjectAddress(expr.variable))
container_type = self.get_c_type(expr.variable.class_type)
return f'{container_type}_drop({variable_address});\n'
Expand Down Expand Up @@ -2206,7 +2225,7 @@ def _print_Assign(self, expr):
if isinstance(rhs, (NumpyFull)):
return prefix_code+self.arrayFill(expr)
lhs = self._print(expr.lhs)
if isinstance(rhs, (PythonList, PythonSet)):
if isinstance(rhs, (PythonList, PythonSet, PythonDict)):
return prefix_code+self.init_stc_container(rhs, expr)
rhs = self._print(expr.rhs)
return prefix_code+'{} = {};\n'.format(lhs, rhs)
Expand Down
5 changes: 4 additions & 1 deletion pyccel/codegen/wrapper/c_to_python_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,10 @@ def _get_untranslatable_function(self, name, scope, original_function, error_msg
The new function which raises the error.
"""
func_args = [FunctionDefArgument(self.get_new_PyObject(n)) for n in ("self", "args", "kwargs")]
func_results = [FunctionDefResult(self.get_new_PyObject("result", is_temp=True))]
if self._error_exit_code is Nil():
func_results = [FunctionDefResult(self.get_new_PyObject("result", is_temp=True))]
else:
func_results = [FunctionDefResult(self.scope.get_temporary_variable(self._error_exit_code.class_type, "result"))]
function = PyFunctionDef(name = name, arguments = func_args, results = func_results,
body = [FunctionCall(PyErr_SetString, [PyNotImplementedError,
LiteralString(error_msg)]),
Expand Down
29 changes: 17 additions & 12 deletions tests/epyccel/test_epyccel_variable_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import pytest

from pyccel import epyccel
from pyccel.errors.errors import PyccelSemanticError, Errors
from pyccel.errors.errors import PyccelSemanticError
from pyccel.decorators import allow_negative_index, stack_array

@pytest.fixture( params=[
Expand Down Expand Up @@ -272,17 +272,22 @@ def homogeneous_list_annotation():
assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation()
assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation()))

@pytest.mark.parametrize('lang',
[pytest.param("python", marks = pytest.mark.python)])
def test_dict_empty_init(lang):
def dict_empty_init():
def test_dict_int_float(stc_language):
def dict_int_float():
# Not valid in Python 3.8
a : dict[int, float] #pylint: disable=unsubscriptable-object
a : dict[int, float] #pylint: disable=unsubscriptable-object,unused-variable
a = {1:1.0, 2:2.0}
return a

epyc_dict_empty_init = epyccel(dict_empty_init, language = lang)
pyccel_result = epyc_dict_empty_init()
python_result = dict_empty_init()
assert isinstance(python_result, type(pyccel_result))
assert python_result == pyccel_result
epyc_dict_int_float = epyccel(dict_int_float, language = stc_language)
epyc_dict_int_float()
dict_int_float()

def test_dict_empty_init(stc_language):
def dict_empty_init():
# Not valid in Python 3.8
a : dict[int, float] #pylint: disable=unsubscriptable-object,unused-variable
a = {}

epyc_dict_empty_init = epyccel(dict_empty_init, language = stc_language)
epyc_dict_empty_init()
dict_empty_init()

0 comments on commit 09c6b74

Please sign in to comment.