Skip to content

Commit

Permalink
first cut at a hpy test
Browse files Browse the repository at this point in the history
  • Loading branch information
mattip committed Jun 1, 2021
1 parent 26257cc commit 11342a9
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 9 deletions.
19 changes: 17 additions & 2 deletions Cython/Compiler/ModuleNode.py
Expand Up @@ -7,14 +7,15 @@
import cython
cython.declare(Naming=object, Options=object, PyrexTypes=object, TypeSlots=object,
error=object, warning=object, py_object_type=object, UtilityCode=object,
EncodedString=object, re=object)
EncodedString=object, re=object, textwrap=object)

from collections import defaultdict
import json
import operator
import os
import re
import sys
import textwrap

from .PyrexTypes import CPtrType
from . import Future
Expand Down Expand Up @@ -198,6 +199,9 @@ def prepare_utility_code(self):
entry.type.create_type_wrapper(env)

def process_implementation(self, options, result):
""" called in the pipeline as the implementation of the top-level
``generate_pyx_code stage``.
"""
env = self.scope
env.return_type = PyrexTypes.c_void_type
self.referenced_modules = []
Expand Down Expand Up @@ -360,7 +364,6 @@ def api_entries(entries, pxd=0):
h_code.putln('#ifdef __MINGW64__')
h_code.putln('#define MS_WIN64')
h_code.putln('#endif')

h_code.putln('#include "Python.h"')
if result.h_file:
h_filename = os.path.basename(result.h_file)
Expand Down Expand Up @@ -748,6 +751,18 @@ def _put_setup_code(self, code, name):
code.put(UtilityCode.load_as_string(name, "ModuleSetupCode.c")[1])

def generate_module_preamble(self, env, options, cimported_modules, metadata, code):
if options.hpy:
inc = Code.IncludeCode(initial=True, verbatim=textwrap.dedent("""
#ifdef HPY
#include "HPy.h"
#error asdfasdfasdf
#else
#include "Python.h"
#endif
"""))
else:
inc = Code.IncludeCode("Python.h", initial=True)
env.process_include(inc)
code.put_generated_by()
if metadata:
code.putln("/* BEGIN: Cython Metadata")
Expand Down
5 changes: 4 additions & 1 deletion Cython/Compiler/Options.py
Expand Up @@ -327,6 +327,7 @@ def normalise_encoding_name(option_name, encoding):
'c_string_encoding': normalise_encoding_name,
'trashcan': bool,
'total_ordering': bool,
'hpy': bool,
}

for key, val in _directive_defaults.items():
Expand Down Expand Up @@ -371,6 +372,7 @@ def normalise_encoding_name(option_name, encoding):
'iterable_coroutine': ('module', 'function'),
'trashcan' : ('cclass',),
'total_ordering': ('cclass', ),
'hpy': ('module', 'function'),
}


Expand Down Expand Up @@ -738,5 +740,6 @@ def to_fingerprint(item):
build_dir=None,
cache=None,
create_extension=None,
np_pythran=False
np_pythran=False,
hpy=False,
)
15 changes: 15 additions & 0 deletions Cython/Compiler/ParseTreeTransforms.py
Expand Up @@ -3672,3 +3672,18 @@ def serialize_local_variables(self, entries):

self.tb.start('LocalVar', attrs)
self.tb.end('LocalVar')

class HPy(CythonTransform):
"""
If a @cpython.hyp decorator is used
- set the global context option
- set a node attribute
In the future, this could replace a cpython node with an hpy node
"""

def visit_Node(self, node):
if self.current_directives.get('hpy', False):
node.is_hpy = 1
self.context.options.hpy = True
self._process_children(node)
return node
3 changes: 2 additions & 1 deletion Cython/Compiler/Pipeline.py
Expand Up @@ -150,7 +150,7 @@ def create_pipeline(context, mode, exclude_classes=()):
from .ParseTreeTransforms import CalculateQualifiedNamesTransform
from .TypeInference import MarkParallelAssignments, MarkOverflowingArithmetic
from .ParseTreeTransforms import AdjustDefByDirectives, AlignFunctionDefinitions, AutoCpdefFunctionDefinitions
from .ParseTreeTransforms import RemoveUnreachableCode, GilCheck
from .ParseTreeTransforms import RemoveUnreachableCode, GilCheck, HPy
from .FlowControl import ControlFlowAnalysis
from .AnalysedTreeTransforms import AutoTestDictTransform
from .AutoDocTransforms import EmbedSignature
Expand Down Expand Up @@ -213,6 +213,7 @@ def create_pipeline(context, mode, exclude_classes=()):
AnalyseExpressionsTransform(context),
FindInvalidUseOfFusedTypes(context),
ExpandInplaceOperators(context),
HPy(context),
IterationTransform(context),
SwitchTransform(context),
OptimizeBuiltinCalls(context), ## Necessary?
Expand Down
3 changes: 2 additions & 1 deletion Cython/Compiler/Symtab.py
Expand Up @@ -1259,7 +1259,8 @@ def __init__(self, name, parent_module, context):
for var_name in ['__builtins__', '__name__', '__file__', '__doc__', '__path__',
'__spec__', '__loader__', '__package__', '__cached__']:
self.declare_var(EncodedString(var_name), py_object_type, None)
self.process_include(Code.IncludeCode("Python.h", initial=True))
# now done in ModuleNode as env.process_include() for HPy
# self.process_include(Code.IncludeCode("Python.h", initial=True))

def qualifying_scope(self):
return self.parent_module
Expand Down
3 changes: 2 additions & 1 deletion Cython/Shadow.py
Expand Up @@ -121,7 +121,8 @@ class _Optimization(object):
overflowcheck.fold = optimization.use_switch = \
optimization.unpack_method_calls = lambda arg: _EmptyDecoratorAndManager()

final = internal = type_version_tag = no_gc_clear = no_gc = total_ordering = _empty_decorator
final = internal = type_version_tag = no_gc_clear = no_gc = \
total_ordering = hpy = _empty_decorator

binding = lambda _: _empty_decorator

Expand Down
15 changes: 12 additions & 3 deletions runtests.py
Expand Up @@ -129,6 +129,7 @@ def get_distutils_distro(_cache=[]):
'tag:ipython': 'IPython.testing.globalipapp',
'tag:jedi': 'jedi_BROKEN_AND_DISABLED',
'tag:test.support': 'test.support', # support module for CPython unit tests
'tag:hpy': 'hpy.devel',

This comment has been minimized.

Copy link
@mattip

mattip Jun 1, 2021

Author Owner

This fails, since importing hpy is not that simple. Comment this out to output some c code from

python runtests.py hpy  --no-cleanup --no-capture -vv --failfast
}

def patch_inspect_isfunction():
Expand Down Expand Up @@ -816,17 +817,21 @@ def build_tests(self, test_class, path, workdir, module, expect_errors, tags):
pythran_dir = pythran_ext['include_dirs'][0]

preparse_list = tags.get('preparse', ['id'])
hpy = 'hpy' in tags.get('tag', '')
tests = [ self.build_test(test_class, path, workdir, module, tags, language, language_level,
expect_errors, expect_warnings, warning_errors, preparse,
pythran_dir if language == "cpp" else None)
pythran_dir if language == "cpp" else None,
hpy=hpy,
)
for language in languages
for preparse in preparse_list
for language_level in language_levels
]
return tests

def build_test(self, test_class, path, workdir, module, tags, language, language_level,
expect_errors, expect_warnings, warning_errors, preparse, pythran_dir):
expect_errors, expect_warnings, warning_errors, preparse, pythran_dir,
hpy=False):
language_workdir = os.path.join(workdir, language)
if not os.path.exists(language_workdir):
os.makedirs(language_workdir)
Expand All @@ -852,6 +857,7 @@ def build_test(self, test_class, path, workdir, module, tags, language, language
test_determinism=self.test_determinism,
common_utility_dir=self.common_utility_dir,
pythran_dir=pythran_dir,
hpy=hpy,
stats=self.stats)


Expand Down Expand Up @@ -898,7 +904,7 @@ class CythonCompileTestCase(unittest.TestCase):
def __init__(self, test_directory, workdir, module, tags, language='c', preparse='id',
expect_errors=False, expect_warnings=False, annotate=False, cleanup_workdir=True,
cleanup_sharedlibs=True, cleanup_failures=True, cython_only=False, test_selector=None,
fork=True, language_level=2, warning_errors=False,
fork=True, language_level=2, warning_errors=False, hpy=False,
test_determinism=False,
common_utility_dir=None, pythran_dir=None, stats=None):
self.test_directory = test_directory
Expand All @@ -922,6 +928,7 @@ def __init__(self, test_directory, workdir, module, tags, language='c', preparse
self.test_determinism = test_determinism
self.common_utility_dir = common_utility_dir
self.pythran_dir = pythran_dir
self.hpy = hpy
self.stats = stats
unittest.TestCase.__init__(self)

Expand Down Expand Up @@ -1154,6 +1161,8 @@ def run_distutils(self, test_directory, module, workdir, incdir,

ext_compile_flags = CFLAGS[:]
ext_compile_defines = CDEFS[:]
if self.hpy:
ext_compile_defines.append(('HPY', 1))

if build_extension.compiler == 'mingw32':
ext_compile_flags.append('-Wno-format')
Expand Down
19 changes: 19 additions & 0 deletions tests/run/hpy_basic.py
@@ -0,0 +1,19 @@
#mode: run
#tag: hpy

import cython

@cython.hpy
def add_int_hpy(a:int, b:int):
"""
>>> add_int_hpy(1, 2)
3
"""
return a + b

def add_int_capi(a:int, b:int):
"""
>>> add_int_capi(1, 2)
3
"""
return a + b

0 comments on commit 11342a9

Please sign in to comment.