Skip to content

Commit

Permalink
Merge pull request #1386 from spcl/py312
Browse files Browse the repository at this point in the history
Python 3.12
  • Loading branch information
alexnick83 authored Oct 9, 2023
2 parents e608c2c + 159033e commit 291e98d
Show file tree
Hide file tree
Showing 19 changed files with 237 additions and 88 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/general-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7,'3.11']
python-version: [3.7,'3.12']
simplify: [0,1,autoopt]

steps:
Expand Down
2 changes: 1 addition & 1 deletion dace/codegen/control_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
x < 5
/------>[s2]--------\\
[s1] \ ->[s5]
[s1] \\ ->[s5]
------>[s3]->[s4]--/
x >= 5
Expand Down
46 changes: 32 additions & 14 deletions dace/codegen/cppunparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@
from dace import dtypes
from dace.codegen.tools import type_inference


if sys.version_info < (3, 8):
BytesConstant = ast.Bytes
EllipsisConstant = ast.Ellipsis
NameConstant = ast.NameConstant
NumConstant = ast.Num
StrConstant = ast.Str
else:
BytesConstant = ast.Constant
EllipsisConstant = ast.Constant
NameConstant = ast.Constant
NumConstant = ast.Constant
StrConstant = ast.Constant


# Large float and imaginary literals get turned into infinities in the AST.
# We unparse those infinities to INFSTR.
INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1)
Expand Down Expand Up @@ -574,7 +589,7 @@ def _generic_FunctionDef(self, t, is_async=False):
self.write('/* async */ ')

if getattr(t, "returns", False):
if isinstance(t.returns, ast.NameConstant):
if isinstance(t.returns, NameConstant):
if t.returns.value is None:
self.write('void')
else:
Expand Down Expand Up @@ -729,25 +744,26 @@ def _Repr(self, t):
raise NotImplementedError('Invalid C++')

def _Num(self, t):
repr_n = repr(t.n)
t_n = t.value if sys.version_info >= (3, 8) else t.n
repr_n = repr(t_n)
# For complex values, use DTYPE_TO_TYPECLASS dictionary
if isinstance(t.n, complex):
if isinstance(t_n, complex):
dtype = dtypes.DTYPE_TO_TYPECLASS[complex]

# Handle large integer values
if isinstance(t.n, int):
bits = t.n.bit_length()
if isinstance(t_n, int):
bits = t_n.bit_length()
if bits == 32: # Integer, potentially unsigned
if t.n >= 0: # unsigned
if t_n >= 0: # unsigned
repr_n += 'U'
else: # signed, 64-bit
repr_n += 'LL'
elif 32 < bits <= 63:
repr_n += 'LL'
elif bits == 64 and t.n >= 0:
elif bits == 64 and t_n >= 0:
repr_n += 'ULL'
elif bits >= 64:
warnings.warn(f'Value wider than 64 bits encountered in expression ({t.n}), emitting as-is')
warnings.warn(f'Value wider than 64 bits encountered in expression ({t_n}), emitting as-is')

if repr_n.endswith("j"):
self.write("%s(0, %s)" % (dtype, repr_n.replace("inf", INFSTR)[:-1]))
Expand Down Expand Up @@ -898,13 +914,13 @@ def _BinOp(self, t):
self.write(")")
# Special cases for powers
elif t.op.__class__.__name__ == 'Pow':
if isinstance(t.right, (ast.Num, ast.Constant, ast.UnaryOp)):
if isinstance(t.right, (NumConstant, ast.Constant, ast.UnaryOp)):
power = None
if isinstance(t.right, (ast.Num, ast.Constant)):
power = t.right.n
if isinstance(t.right, (NumConstant, ast.Constant)):
power = t.right.value if sys.version_info >= (3, 8) else t.right.n
elif isinstance(t.right, ast.UnaryOp) and isinstance(t.right.op, ast.USub):
if isinstance(t.right.operand, (ast.Num, ast.Constant)):
power = -t.right.operand.n
if isinstance(t.right.operand, (NumConstant, ast.Constant)):
power = - (t.right.operand.value if sys.version_info >= (3, 8) else t.right.operand.n)

if power is not None and int(power) == power:
negative = power < 0
Expand Down Expand Up @@ -984,7 +1000,9 @@ def _Attribute(self, t):
# Special case: 3.__abs__() is a syntax error, so if t.value
# is an integer literal then we need to either parenthesize
# it or add an extra space to get 3 .__abs__().
if (isinstance(t.value, (ast.Num, ast.Constant)) and isinstance(t.value.n, int)):
if isinstance(t.value, ast.Constant) and isinstance(t.value.value, int):
self.write(" ")
elif sys.version_info < (3, 8) and isinstance(t.value, ast.Num) and isinstance(t.value.n, int):
self.write(" ")
if (isinstance(t.value, ast.Name) and t.value.id in ('dace', 'dace::math', 'dace::cmath')):
self.write("::")
Expand Down
2 changes: 1 addition & 1 deletion dace/codegen/instrumentation/papi.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ class PAPIUtils(object):
def available_counters() -> Dict[str, int]:
"""
Returns the available PAPI counters on this machine. Only works on
\*nix based systems with ``grep`` and ``papi-tools`` installed.
*nix based systems with ``grep`` and ``papi-tools`` installed.
:return: A set of available PAPI counters in the form of a dictionary
mapping from counter name to the number of native hardware
Expand Down
6 changes: 4 additions & 2 deletions dace/codegen/targets/cpp.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2019-2021 ETH Zurich and the DaCe authors. All rights reserved.
# Copyright 2019-2023 ETH Zurich and the DaCe authors. All rights reserved.
"""
Helper functions for C++ code generation.
NOTE: The C++ code generator is currently located in cpu.py.
Expand All @@ -9,6 +9,7 @@
import itertools
import math
import numbers
import sys
import warnings

import sympy as sp
Expand Down Expand Up @@ -1275,7 +1276,8 @@ def visit_BinOp(self, node: ast.BinOp):
evaluated_constant = symbolic.evaluate(unparsed, self.constants)
evaluated = symbolic.symstr(evaluated_constant, cpp_mode=True)
value = ast.parse(evaluated).body[0].value
if isinstance(evaluated_node, numbers.Number) and evaluated_node != value.n:
if isinstance(evaluated_node, numbers.Number) and evaluated_node != (
value.value if sys.version_info >= (3, 8) else value.n):
raise TypeError
node.right = ast.parse(evaluated).body[0].value
except (TypeError, AttributeError, NameError, KeyError, ValueError, SyntaxError):
Expand Down
10 changes: 9 additions & 1 deletion dace/codegen/tools/type_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,15 @@ def _BinOp(t, symbols, inferred_symbols):
return dtypes.result_type_of(type_left, type_right)
# Special case for integer power
elif t.op.__class__.__name__ == 'Pow':
if (isinstance(t.right, (ast.Num, ast.Constant)) and int(t.right.n) == t.right.n and t.right.n >= 0):
if (sys.version_info >= (3, 8) and isinstance(t.right, ast.Constant) and
int(t.right.value) == t.right.value and t.right.value >= 0):
if t.right.value != 0:
type_left = _dispatch(t.left, symbols, inferred_symbols)
for i in range(int(t.right.n) - 1):
_dispatch(t.left, symbols, inferred_symbols)
return dtypes.result_type_of(type_left, dtypes.typeclass(np.uint32))
elif (sys.version_info < (3, 8) and isinstance(t.right, ast.Num) and
int(t.right.n) == t.right.n and t.right.n >= 0):
if t.right.n != 0:
type_left = _dispatch(t.left, symbols, inferred_symbols)
for i in range(int(t.right.n) - 1):
Expand Down
32 changes: 20 additions & 12 deletions dace/frontend/python/astutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
from dace import dtypes, symbolic


if sys.version_info >= (3, 8):
NumConstant = ast.Constant
else:
NumConstant = ast.Num


def _remove_outer_indentation(src: str):
""" Removes extra indentation from a source Python function.
Expand Down Expand Up @@ -66,8 +72,9 @@ def is_constant(node: ast.AST) -> bool:
if sys.version_info >= (3, 8):
if isinstance(node, ast.Constant):
return True
if isinstance(node, (ast.Num, ast.Str, ast.NameConstant)): # For compatibility
return True
else:
if isinstance(node, (ast.Num, ast.Str, ast.NameConstant)): # For compatibility
return True
return False


Expand All @@ -82,13 +89,14 @@ def evalnode(node: ast.AST, gvars: Dict[str, Any]) -> Any:
"""
if not isinstance(node, ast.AST):
return node
if isinstance(node, ast.Index): # For compatibility
if sys.version_info < (3, 9) and isinstance(node, ast.Index): # For compatibility
node = node.value
if isinstance(node, ast.Num): # For compatibility
return node.n
if sys.version_info >= (3, 8):
if isinstance(node, ast.Constant):
return node.value
else:
if isinstance(node, ast.Num): # For compatibility
return node.n

# Replace internal constants with their values
node = copy_tree(node)
Expand All @@ -112,7 +120,7 @@ def rname(node):

if isinstance(node, str):
return node
if isinstance(node, ast.Num):
if sys.version_info < (3, 8) and isinstance(node, ast.Num):
return str(node.n)
if isinstance(node, ast.Name): # form x
return node.id
Expand Down Expand Up @@ -174,11 +182,11 @@ def subscript_to_ast_slice(node, without_array=False):

# Python <3.9 compatibility
result_slice = None
if isinstance(node.slice, ast.Index):
if sys.version_info < (3, 9) and isinstance(node.slice, ast.Index):
slc = node.slice.value
if not isinstance(slc, ast.Tuple):
result_slice = [slc]
elif isinstance(node.slice, ast.ExtSlice):
elif sys.version_info < (3, 9) and isinstance(node.slice, ast.ExtSlice):
slc = tuple(node.slice.dims)
else:
slc = node.slice
Expand All @@ -196,7 +204,7 @@ def subscript_to_ast_slice(node, without_array=False):
# Slice
if isinstance(s, ast.Slice):
result_slice.append((s.lower, s.upper, s.step))
elif isinstance(s, ast.Index): # Index (Python <3.9)
elif sys.version_info < (3, 9) and isinstance(s, ast.Index): # Index (Python <3.9)
result_slice.append(s.value)
else: # Index
result_slice.append(s)
Expand Down Expand Up @@ -226,7 +234,7 @@ def _Subscript(self, t):
self.dispatch(t.value)
self.write('[')
# Compatibility
if isinstance(t.slice, ast.Index):
if sys.version_info < (3, 9) and isinstance(t.slice, ast.Index):
slc = t.slice.value
else:
slc = t.slice
Expand Down Expand Up @@ -600,9 +608,9 @@ def visit_Name(self, node: ast.Name):
def visit_Constant(self, node):
return self.visit_Num(node)

def visit_Num(self, node: ast.Num):
def visit_Num(self, node: NumConstant):
newname = f'__uu{self.id}'
self.gvars[newname] = node.n
self.gvars[newname] = node.value if sys.version_info >= (3, 8) else node.n
self.id += 1
return ast.copy_location(ast.Name(id=newname, ctx=ast.Load()), node)

Expand Down
24 changes: 20 additions & 4 deletions dace/frontend/python/memlet_parser.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright 2019-2021 ETH Zurich and the DaCe authors. All rights reserved.
# Copyright 2019-2023 ETH Zurich and the DaCe authors. All rights reserved.
import ast
import copy
import re
import sys
from collections import namedtuple
from typing import Any, Dict, List, Optional, Tuple, Union
from dataclasses import dataclass
Expand All @@ -16,6 +16,22 @@
MemletType = Union[ast.Call, ast.Attribute, ast.Subscript, ast.Name]


if sys.version_info < (3, 8):
_simple_ast_nodes = (ast.Constant, ast.Name, ast.NameConstant, ast.Num)
BytesConstant = ast.Bytes
EllipsisConstant = ast.Ellipsis
NameConstant = ast.NameConstant
NumConstant = ast.Num
StrConstant = ast.Str
else:
_simple_ast_nodes = (ast.Constant, ast.Name)
BytesConstant = ast.Constant
EllipsisConstant = ast.Constant
NameConstant = ast.Constant
NumConstant = ast.Constant
StrConstant = ast.Constant


@dataclass
class MemletExpr:
name: str
Expand Down Expand Up @@ -114,7 +130,7 @@ def _fill_missing_slices(das, ast_ndslice, array, indices):
offsets.append(idx)
idx += 1
new_idx += 1
elif (isinstance(dim, ast.Ellipsis) or dim is Ellipsis
elif ((sys.version_info < (3, 8) and isinstance(dim, ast.Ellipsis)) or dim is Ellipsis
or (isinstance(dim, ast.Constant) and dim.value is Ellipsis)
or (isinstance(dim, ast.Name) and dim.id is Ellipsis)):
if has_ellipsis:
Expand All @@ -125,7 +141,7 @@ def _fill_missing_slices(das, ast_ndslice, array, indices):
ndslice[j] = (0, array.shape[j] - 1, 1)
idx += 1
new_idx += 1
elif (dim is None or (isinstance(dim, (ast.Constant, ast.NameConstant)) and dim.value is None)):
elif (dim is None or (isinstance(dim, (ast.Constant, NameConstant)) and dim.value is None)):
new_axes.append(new_idx)
new_idx += 1
# NOTE: Do not increment idx here
Expand Down
Loading

0 comments on commit 291e98d

Please sign in to comment.