Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,17 @@ Using pytest
::

# Run all tests
python -m pytest test/test_cyml_operations.py -v
python -m pytest test/cyml/test_cyml_operations.py -v

# Run a specific test class
python -m pytest test/test_cyml_operations.py::TestCyMLOperations -v
python -m pytest test/cyml/test_cyml_operations.py::TestCyMLOperations -v

# Run a single test
python -m pytest test/test_cyml_operations.py::TestCyMLOperations::test_modulo_operation -v
python -m pytest test/cyml/test_cyml_operations.py::TestCyMLOperations::test_modulo_operation -v

Using unittest
~~~~~~~~~~~~~~
::

cd test
cd test/cyml
python -m unittest test_cyml_operations
63 changes: 53 additions & 10 deletions src/pycropml/transpiler/ast_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,25 @@ def visit_singleassignmentnode(self, node, lhs, rhs, location):
if e is None:
self.notdeclared(name, location)
elif e:
if e in ("list", "dict", "tuple", "array", "intlist", "floatlist", "intarray", "floatarray"):
a = self._compatible_types(
e, value_node['pseudo_type'], "Type error for variable '%s' in function '%s' at line %s: expected type does not match assigned type" % (name, self.function_name, location[0]))
else:
#if value_node["type"] =="custom_call" and value_node["pseudo_type"] is None: value_node["pseudo_type"] = e
if value_node["type"] != "none":
a = self._compatible_types(e, value_node['pseudo_type'], "Type error for variable '%s' in function '%s' at line %s: expected type does not match assigned type" % (
name, self.function_name, location[0]))
# if value_node["type"] =="custom_call" and value_node["pseudo_type"] is None: value_node["pseudo_type"] = e
if value_node["type"] != "none":
err_msg = (
"Type error for variable '%s' in function '%s' at line %s: "
"expected type does not match assigned type"
) % (name, self.function_name, location[0])
compatibility = self._compatible_types(
e,
value_node['pseudo_type'],
err_msg,
silent=True
)
if compatibility is False:
raise type_check_error(
err_msg,
location,
self.lines[location[0]],
wrong_type=value_node['pseudo_type']
)
z = {
'type': 'assignment',
'target': {
Expand Down Expand Up @@ -908,11 +919,25 @@ def _translate_builtin_method_call(self, class_type, base, message, args, locati
if base["pseudo_type"] =="list":
self.type_env.top[base["name"]] = [
"list", args[0]["pseudo_type"]]
return api.expand([base] + args)
try:
return api.expand([base] + args)
except PseudoCythonTypeCheckError as exc:
raise type_check_error(
str(exc),
location,
self.lines[location[0]]
) from None
else:
for count, b in api.items():
if len(args) == count:
return b.expand([base] + args)
try:
return b.expand([base] + args)
except PseudoCythonTypeCheckError as exc:
raise type_check_error(
str(exc),
location,
self.lines[location[0]]
) from None
raise translation_error(
'pseudo-cython doesn\'t support %s%s with %d args' % (
serialize_type(class_type), message, len(args)),
Expand Down Expand Up @@ -1437,6 +1462,24 @@ def visit_cvardefnode(self, node, base_type, declarators, location):
typearray = ["intarray","floatarray","booleanarray","stringarray", "strarray"]
is_enum_type = actual_type_name in self._enum_names()
for de in declarators:
# Every declaration must define an explicit variable name.
if isinstance(de, Nodes.CArrayDeclaratorNode):
if hasattr(de, 'base') and hasattr(de.base, 'base') and hasattr(de.base.base, 'name'):
declared_name = de.base.base.name
elif hasattr(de, 'base') and hasattr(de.base, 'name'):
declared_name = de.base.name
else:
declared_name = None
else:
declared_name = getattr(de, 'name', None)

if not declared_name:
raise type_check_error(
"invalid declaration: missing variable name",
location,
self.lines[location[0]] if location and getattr(self, 'lines', None) else None
)

if not isinstance(de, Nodes.CArrayDeclaratorNode):
if not self.isattr and self.type_env[de.name]:
raise PseudoCythonTypeCheckError(
Expand Down
12 changes: 6 additions & 6 deletions test/cyml/logs/test_array_declaration.log
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
2026-03-29 11:49:28 DEBUG [pycropml.transpiler.main] Parsing source input
2026-03-29 11:49:28 DEBUG [pycropml.transpiler.parser] Starting parse (input type=str)
2026-03-29 11:49:28 DEBUG [pycropml.transpiler.parser] Parse succeeded
2026-03-29 11:49:28 DEBUG [pycropml.transpiler.main] Parsing completed
2026-03-29 11:49:28 DEBUG [pycropml.transpiler.main] Building AST
2026-03-29 11:49:28 DEBUG [pycropml.transpiler.main] AST build completed
2026-03-29 13:34:36 DEBUG [pycropml.transpiler.main] Parsing source input
2026-03-29 13:34:36 DEBUG [pycropml.transpiler.parser] Starting parse (input type=str)
2026-03-29 13:34:36 DEBUG [pycropml.transpiler.parser] Parse succeeded
2026-03-29 13:34:36 DEBUG [pycropml.transpiler.main] Parsing completed
2026-03-29 13:34:36 DEBUG [pycropml.transpiler.main] Building AST
2026-03-29 13:34:36 DEBUG [pycropml.transpiler.main] AST build completed
4 changes: 2 additions & 2 deletions test/cyml/test_cyml_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ def test_list():
cdef int length, total
length = len(numbers)
total = sum(numbers)
numbers.append(6)
numbers.append(4)
return total
"""
result = self._transpile_code(code)
Expand All @@ -235,7 +235,7 @@ def test_array_declaration(self):
from tata import toto
def test_array(int s=5):
cdef float temps[10] # declare a C-style array of 10 floats
cdef floatarray[10]
cdef floatarray a
cdef int size
size = len(temps)
return size
Expand Down
Loading