Skip to content

Commit 1d6b2ce

Browse files
authored
Merge pull request #72 from nikkirad/nikrad
Recognize where clauses
2 parents 0c164bd + 851c35b commit 1d6b2ce

File tree

2 files changed

+95
-60
lines changed

2 files changed

+95
-60
lines changed

Diff for: sphinxcontrib/chapeldomain/__init__.py

+19-5
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@
4848
([\w$.]*\.)? # class name(s)
4949
([\w\+\-/\*$\<\=\>\!]+) \s* # function or method name
5050
(?:\((.*?)\))? # opt: arguments
51-
(\s+(?:const\s)? \w+| # or return intent
52-
\s* : \s* [^:]+| # or return type
53-
\s+(?:const\s)? \w+\s* : \s* [^:]+ # or return intent and type
51+
(\s+(?:const\s)? (?:\w+?)| # or return intent
52+
\s* : \s* (?:[^:]+?)| # or return type
53+
\s+(?:const\s)? \w+\s* : \s* (?:[^:]+?) # or return intent and type
54+
)?
55+
(\s+where\s+.* # Where clause
5456
)?
5557
$""", re.VERBOSE)
5658

@@ -221,7 +223,7 @@ def _get_proc_like_prefix(self, sig):
221223
if sig_match is None:
222224
return ChapelObject.get_signature_prefix(self, sig)
223225

224-
prefixes, _, _, _, _ = sig_match.groups()
226+
prefixes, _, _, _, _, _ = sig_match.groups()
225227
if prefixes:
226228
return prefixes.strip() + ' '
227229
elif self.objtype.startswith('iter'):
@@ -285,14 +287,20 @@ def handle_signature(self, sig, signode):
285287
raise ValueError('Signature does not parse: {0}'.format(sig))
286288
func_prefix, name_prefix, name, retann = sig_match.groups()
287289
arglist = None
290+
where_clause = None
288291
else:
289292
sig_match = chpl_sig_pattern.match(sig)
290293
if sig_match is None:
291294
raise ValueError('Signature does not parse: {0}'.format(sig))
292295

293-
func_prefix, name_prefix, name, arglist, retann = \
296+
func_prefix, name_prefix, name, arglist, retann, where_clause = \
294297
sig_match.groups()
295298

299+
# check if where clause is valid
300+
if where_clause is not None and not self._is_proc_like():
301+
raise ValueError('A where clause has been used on'
302+
' a non-proc-like directive.')
303+
296304
modname = self.options.get(
297305
'module', self.env.temp_data.get('chpl:module'))
298306
classname = self.env.temp_data.get('chpl:class')
@@ -346,13 +354,19 @@ def handle_signature(self, sig, signode):
346354
signode += addnodes.desc_type(retann, retann)
347355
if anno:
348356
signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
357+
if where_clause:
358+
signode += addnodes.desc_annotation(' ' + where_clause,
359+
' ' + where_clause)
349360
return fullname, name_prefix
350361

351362
self._pseudo_parse_arglist(signode, arglist)
352363
if retann:
353364
signode += addnodes.desc_type(retann, retann)
354365
if anno:
355366
signode += addnodes.desc_annotation(' ' + anno, ' ' + anno)
367+
if where_clause:
368+
signode += addnodes.desc_annotation(' ' + where_clause,
369+
' ' + where_clause)
356370
return fullname, name_prefix
357371

358372
def get_index_text(self, modname, name):

Diff for: test/test_chapeldomain.py

+76-55
Original file line numberDiff line numberDiff line change
@@ -643,19 +643,20 @@ class SigPatternTests(PatternTestCase):
643643
longMessage = True
644644
pattern = chpl_sig_pattern
645645

646-
def check_sig(self, sig, func_prefix, name_prefix, name, arglist, retann):
646+
def check_sig(self, sig, func_prefix, name_prefix, name, arglist, retann, where_clause):
647647
"""Verify signature results in appropriate matches."""
648648
fail_msg = 'sig: {0}'.format(sig)
649649

650650
match = self.pattern.match(sig)
651651
self.assertIsNotNone(match, msg=fail_msg)
652652

653-
(actual_func_prefix, actual_name_prefix, actual_name, actual_arglist, actual_retann) = match.groups()
653+
(actual_func_prefix, actual_name_prefix, actual_name, actual_arglist, actual_retann, actual_where_clause) = match.groups()
654654
self.assertEqual(func_prefix, actual_func_prefix, msg=fail_msg)
655655
self.assertEqual(name_prefix, actual_name_prefix, msg=fail_msg)
656656
self.assertEqual(name, actual_name, msg=fail_msg)
657657
self.assertEqual(arglist, actual_arglist, msg=fail_msg)
658658
self.assertEqual(retann, actual_retann, msg=fail_msg)
659+
self.assertEqual(where_clause, actual_where_clause, msg=fail_msg)
659660

660661
def test_does_not_match(self):
661662
"""Verify various signatures that should not match."""
@@ -685,7 +686,7 @@ def test_no_parens(self):
685686
'**',
686687
]
687688
for sig in test_cases:
688-
self.check_sig(sig, None, None, sig, None, None)
689+
self.check_sig(sig, None, None, sig, None, None, None)
689690

690691
def test_no_args(self):
691692
"""Verify various functions with no args parse correctly."""
@@ -704,7 +705,7 @@ def test_no_args(self):
704705
('x ()', 'x'),
705706
]
706707
for sig, name in test_cases:
707-
self.check_sig(sig, None, None, name, '', None)
708+
self.check_sig(sig, None, None, name, '', None, None)
708709

709710
def test_with_args(self):
710711
"""Verify function signatures with arguments parse correctly."""
@@ -720,26 +721,26 @@ def test_with_args(self):
720721
('++++++++++++++++++++ ( +++ )', '++++++++++++++++++++', ' +++ '),
721722
]
722723
for sig, name, arglist in test_cases:
723-
self.check_sig(sig, None, None, name, arglist, None)
724+
self.check_sig(sig, None, None, name, arglist, None, None)
724725

725726
def test_with_return_type(self):
726727
"""Verify function signatures with return types parse correctly."""
727728
test_cases = [
728-
('x(): int', 'x', '', ': int'),
729-
('x(): MyMod.MyClass', 'x', '', ': MyMod.MyClass'),
730-
('x(): int(32)', 'x', '', ': int(32)'),
731-
('x():int(32)', 'x', '', ':int(32)'),
732-
('x(y:int(64)):int(32)', 'x', 'y:int(64)', ':int(32)'),
733-
('x(y:int(64), d: domain(r=2, i=int, s=true)): [{1..5}] real', 'x', 'y:int(64), d: domain(r=2, i=int, s=true)', ': [{1..5}] real'),
734-
('x(): domain(1)', 'x', '', ': domain(1)'),
735-
('x(): [{1..n}] BigNum', 'x', '', ': [{1..n}] BigNum'),
736-
('x(): nil', 'x', '', ': nil'),
737-
('x() ref', 'x', '', ' ref'),
738-
('x() const', 'x', '', ' const'),
739-
('x(ref x:int(32)) const', 'x', 'ref x:int(32)', ' const'),
729+
('x(): int', 'x', '', ': int', None),
730+
('x(): MyMod.MyClass', 'x', '', ': MyMod.MyClass', None),
731+
('x(): int(32)', 'x', '', ': int(32)', None),
732+
('x():int(32)', 'x', '', ':int(32)', None),
733+
('x(y:int(64)):int(32)', 'x', 'y:int(64)', ':int(32)', None),
734+
('x(y:int(64), d: domain(r=2, i=int, s=true)): [{1..5}] real', 'x', 'y:int(64), d: domain(r=2, i=int, s=true)', ': [{1..5}] real', None),
735+
('x(): domain(1)', 'x', '', ': domain(1)', None),
736+
('x(): [{1..n}] BigNum', 'x', '', ': [{1..n}] BigNum', None),
737+
('x(): nil', 'x', '', ': nil', None),
738+
('x() ref', 'x', '', ' ref', None),
739+
('x() const', 'x', '', ' const', None),
740+
('x(ref x:int(32)) const', 'x', 'ref x:int(32)', ' const', None),
740741
]
741-
for sig, name, arglist, retann in test_cases:
742-
self.check_sig(sig, None, None, name, arglist, retann)
742+
for sig, name, arglist, retann, where_clause in test_cases:
743+
self.check_sig(sig, None, None, name, arglist, retann, where_clause)
743744

744745
def test_with_class_names(self):
745746
"""Verify function signatures with class names parse correctly."""
@@ -754,7 +755,7 @@ def test_with_class_names(self):
754755
('MyMod.MyClass.foo()', 'MyMod.MyClass.', 'foo', ''),
755756
]
756757
for sig, class_name, name, arglist in test_cases:
757-
self.check_sig(sig, None, class_name, name, arglist, None)
758+
self.check_sig(sig, None, class_name, name, arglist, None, None)
758759

759760
def test_with_prefixes(self):
760761
"""Verify functions with prefixes parse correctly."""
@@ -766,51 +767,71 @@ def test_with_prefixes(self):
766767
('inline operator +', 'inline operator ', '+', None),
767768
]
768769
for sig, prefix, name, arglist in test_cases:
769-
self.check_sig(sig, prefix, None, name, arglist, None)
770+
self.check_sig(sig, prefix, None, name, arglist, None, None)
771+
772+
def test_with_where_clause(self):
773+
"""Verify functions with where clauses parse correctly."""
774+
test_cases = [
775+
('proc processArr(arr: [1..n] int, f: proc (int) int) where n > 0', 'proc ', 'processArr', 'arr: [1..n] int, f: proc (int) int', None, ' where n > 0'),
776+
('proc processArr(arr: []) where arr.elemType == int', 'proc ', 'processArr', 'arr: []', None, ' where arr.elemType == int'),
777+
('proc processDom(dom: domain) where dom.rank == 2', 'proc ', 'processDom', 'dom: domain', None, ' where dom.rank == 2'),
778+
('proc processRec(r: MyRecord) where r.x > 0', 'proc ', 'processRec', 'r: MyRecord', None, ' where r.x > 0'),
779+
('proc processRange(r: [1..n] int) where n > 0', 'proc ', 'processRange', 'r: [1..n] int', None, ' where n > 0'),
780+
('proc processRange(r: range) where r.low > 1', 'proc ', 'processRange', 'r: range', None, ' where r.low > 1'),
781+
('operator + (a: int, b: int) where a > 0', 'operator ', '+', 'a: int, b: int', None, ' where a > 0'),
782+
]
783+
for sig, prefix, name, arglist, retann, where_clause in test_cases:
784+
self.check_sig(sig, prefix, None, name, arglist, retann, where_clause)
770785

771786
def test_with_all(self):
772787
"""Verify fully specified signatures parse correctly."""
773788
test_cases = [
774-
('proc foo() ref', 'proc ', None, 'foo', '', ' ref'),
775-
('iter foo() ref', 'iter ', None, 'foo', '', ' ref'),
776-
('inline proc Vector.pop() ref', 'inline proc ', 'Vector.', 'pop', '', ' ref'),
777-
('inline proc range.first', 'inline proc ', 'range.', 'first', None, None),
778-
('iter Math.fib(n: int(64)): GMP.BigInt', 'iter ', 'Math.', 'fib', 'n: int(64)', ': GMP.BigInt'),
779-
('proc My.Mod.With.Deep.NameSpace.1.2.3.432.foo()', 'proc ', 'My.Mod.With.Deep.NameSpace.1.2.3.432.', 'foo', '', None),
780-
('these() ref', None, None, 'these', '', ' ref'),
781-
('size', None, None, 'size', None, None),
782-
('proc Util.toVector(type eltType, cap=4, offset=0): Containers.Vector', 'proc ', 'Util.', 'toVector', 'type eltType, cap=4, offset=0', ': Containers.Vector'),
783-
('proc MyClass$.lock$(combo$): sync bool', 'proc ', 'MyClass$.', 'lock$', 'combo$', ': sync bool'),
784-
('proc MyClass$.lock$(combo$): sync myBool$', 'proc ', 'MyClass$.', 'lock$', 'combo$', ': sync myBool$'),
785-
('proc type currentTime(): int(64)', 'proc type ', None, 'currentTime', '', ': int(64)'),
786-
('proc param int.someNum(): int(64)', 'proc param ', 'int.', 'someNum', '', ': int(64)'),
787-
('proc MyRs(seed: int(64)): int(64)', 'proc ', None, 'MyRs', 'seed: int(64)', ': int(64)'),
789+
('proc foo where a > b', 'proc ', None, 'foo', None, None, ' where a > b'),
790+
('proc foo() where a > b', 'proc ', None, 'foo', '', None, ' where a > b'),
791+
('proc foo:int where a > b', 'proc ', None, 'foo', None, ':int', ' where a > b'),
792+
('proc foo():int where a > b', 'proc ', None, 'foo', '', ':int', ' where a > b'),
793+
('proc foo ref where a > b', 'proc ', None, 'foo', None, ' ref', ' where a > b'),
794+
('proc foo() ref where a > b', 'proc ', None, 'foo', '', ' ref', ' where a > b'),
795+
('proc foo ref: int where a > b', 'proc ', None, 'foo', None, ' ref: int', ' where a > b'),
796+
('proc foo() ref: int where a > b', 'proc ', None, 'foo', '', ' ref: int', ' where a > b'),
797+
('proc foo() ref', 'proc ', None, 'foo', '', ' ref', None),
798+
('iter foo() ref', 'iter ', None, 'foo', '', ' ref', None),
799+
('inline proc Vector.pop() ref', 'inline proc ', 'Vector.', 'pop', '', ' ref', None),
800+
('inline proc range.first', 'inline proc ', 'range.', 'first', None, None, None),
801+
('iter Math.fib(n: int(64)): GMP.BigInt', 'iter ', 'Math.', 'fib', 'n: int(64)', ': GMP.BigInt', None),
802+
('proc My.Mod.With.Deep.NameSpace.1.2.3.432.foo()', 'proc ', 'My.Mod.With.Deep.NameSpace.1.2.3.432.', 'foo', '', None, None),
803+
('these() ref', None, None, 'these', '', ' ref', None),
804+
('size', None, None, 'size', None, None, None),
805+
('proc Util.toVector(type eltType, cap=4, offset=0): Containers.Vector', 'proc ', 'Util.', 'toVector', 'type eltType, cap=4, offset=0', ': Containers.Vector', None),
806+
('proc MyClass$.lock$(combo$): sync bool', 'proc ', 'MyClass$.', 'lock$', 'combo$', ': sync bool', None),
807+
('proc MyClass$.lock$(combo$): sync myBool$', 'proc ', 'MyClass$.', 'lock$', 'combo$', ': sync myBool$', None),
808+
('proc type currentTime(): int(64)', 'proc type ', None, 'currentTime', '', ': int(64)', None),
809+
('proc param int.someNum(): int(64)', 'proc param ', 'int.', 'someNum', '', ': int(64)', None),
810+
('proc MyRs(seed: int(64)): int(64)', 'proc ', None, 'MyRs', 'seed: int(64)', ': int(64)', None),
788811
('proc RandomStream(seed: int(64) = SeedGenerator.currentTime, param parSafe: bool = true)',
789-
'proc ', None, 'RandomStream', 'seed: int(64) = SeedGenerator.currentTime, param parSafe: bool = true', None),
790-
('class X', 'class ', None, 'X', None, None),
791-
('class MyClass:YourClass', 'class ', None, 'MyClass', None, ':YourClass'),
792-
('class M.C : A, B, C', 'class ', 'M.', 'C', None, ': A, B, C'),
793-
('record R', 'record ', None, 'R', None, None),
794-
('record MyRec:SuRec', 'record ', None, 'MyRec', None, ':SuRec'),
795-
('record N.R : X, Y, Z', 'record ', 'N.', 'R', None, ': X, Y, Z'),
812+
'proc ', None, 'RandomStream', 'seed: int(64) = SeedGenerator.currentTime, param parSafe: bool = true', None, None),
813+
('class X', 'class ', None, 'X', None, None, None),
814+
('class MyClass:YourClass', 'class ', None, 'MyClass', None, ':YourClass', None),
815+
('class M.C : A, B, C', 'class ', 'M.', 'C', None, ': A, B, C', None),
816+
('record R', 'record ', None, 'R', None, None, None),
817+
('record MyRec:SuRec', 'record ', None, 'MyRec', None, ':SuRec', None),
818+
('record N.R : X, Y, Z', 'record ', 'N.', 'R', None, ': X, Y, Z', None),
796819
('proc rcRemote(replicatedVar: [?D] ?MYTYPE, remoteLoc: locale) ref: MYTYPE',
797-
'proc ', None, 'rcRemote', 'replicatedVar: [?D] ?MYTYPE, remoteLoc: locale', ' ref: MYTYPE'),
820+
'proc ', None, 'rcRemote', 'replicatedVar: [?D] ?MYTYPE, remoteLoc: locale', ' ref: MYTYPE', None),
798821
('proc rcLocal(replicatedVar: [?D] ?MYTYPE) ref: MYTYPE',
799-
'proc ', None, 'rcLocal', 'replicatedVar: [?D] ?MYTYPE', ' ref: MYTYPE'),
800-
('proc specialArg(const ref x: int)', 'proc ', None, 'specialArg', 'const ref x: int', None),
801-
('proc specialReturn() const ref', 'proc ', None, 'specialReturn', '', ' const ref'),
802-
('proc constRefArgAndReturn(const ref x: int) const ref', 'proc ', None, 'constRefArgAndReturn', 'const ref x: int', ' const ref'),
803-
('operator string.+(s0: string, s1: string) : string', 'operator ', 'string.', '+', 's0: string, s1: string', ' : string'),
804-
('operator *(s: string, n: integral) : string', 'operator ', None, '*', 's: string, n: integral', ' : string'),
805-
('inline operator string.==(param s0: string, param s1: string) param', 'inline operator ', 'string.', '==', 'param s0: string, param s1: string', ' param'),
806-
('operator bytes.=(ref lhs: bytes, rhs: bytes) : void ', 'operator ', 'bytes.', '=', 'ref lhs: bytes, rhs: bytes', ' : void '),
822+
'proc ', None, 'rcLocal', 'replicatedVar: [?D] ?MYTYPE', ' ref: MYTYPE', None),
823+
('proc specialArg(const ref x: int)', 'proc ', None, 'specialArg', 'const ref x: int', None, None),
824+
('proc specialReturn() const ref', 'proc ', None, 'specialReturn', '', ' const ref', None),
825+
('proc constRefArgAndReturn(const ref x: int) const ref', 'proc ', None, 'constRefArgAndReturn', 'const ref x: int', ' const ref', None),
826+
('operator string.+(s0: string, s1: string) : string', 'operator ', 'string.', '+', 's0: string, s1: string', ' : string', None),
827+
('operator *(s: string, n: integral) : string', 'operator ', None, '*', 's: string, n: integral', ' : string', None),
828+
('inline operator string.==(param s0: string, param s1: string) param', 'inline operator ', 'string.', '==', 'param s0: string, param s1: string', ' param', None),
829+
('operator bytes.=(ref lhs: bytes, rhs: bytes) : void ', 'operator ', 'bytes.', '=', 'ref lhs: bytes, rhs: bytes', ' : void ', None),
807830
# can't handle this pattern, ":" is set as punctuation, and casts don't seem to be doc'd anyway
808831
# ('operator :(x: bytes)', 'operator ', None, ':', 'x: bytes', None),
809-
810832
]
811-
for sig, prefix, class_name, name, arglist, retann in test_cases:
812-
self.check_sig(sig, prefix, class_name, name, arglist, retann)
813-
833+
for sig, prefix, class_name, name, arglist, retann, where_clause in test_cases:
834+
self.check_sig(sig, prefix, class_name, name, arglist, retann, where_clause)
814835

815836
class AttrSigPatternTests(PatternTestCase):
816837
"""Verify chpl_attr_sig_pattern regex."""

0 commit comments

Comments
 (0)