Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Closes #313) permit intrinsic shadowing #418

Merged
merged 23 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
248a618
#313 change Intrinsic match to return None if no. of args differs fro…
arporter Mar 7, 2022
8ad1a22
Merge branch 'master' into 313_permit_intrinsic_shadowing
arporter Jul 28, 2022
335fb07
Merge branch 'master' into 313_permit_intrinsic_shadowing
arporter Jun 12, 2023
999e499
Merge branch 'master' into 313_permit_intrinsic_shadowing
arporter Sep 14, 2023
f50ade6
#313 add wildcard_imports property to SymbolTable
arporter Sep 14, 2023
e8238e0
#313 update Dev Guide
arporter Sep 14, 2023
602b368
#313 check for wildcard imports before raising syntax error on intrin…
arporter Sep 14, 2023
44c3907
#313 add new tests for intrinsic
arporter Sep 14, 2023
22337ad
#313 extend test to get coverage
arporter Sep 14, 2023
207d3ba
#418 add comment
arporter Sep 27, 2023
1500119
#418 improve testing
arporter Sep 28, 2023
911b1ae
#313 further test improvements
arporter Sep 28, 2023
03dc8d1
Merge branch 'master' into 313_permit_intrinsic_shadowing
arporter Sep 28, 2023
6f15622
#313 add node and all_symbols_resolved properties to symbol table.
arporter Oct 20, 2023
6dc0dde
Merge branch 'master' into 313_permit_intrinsic_shadowing
arporter Oct 20, 2023
41f83a3
#313 improve testing of new methods
arporter Oct 20, 2023
b04834c
Merge branch '313_permit_intrinsic_shadowing' of github.com:stfc/fpar…
arporter Oct 20, 2023
9029e9b
#313 improve testing of wildcard_imports()
arporter Oct 20, 2023
45c9dab
#418 updates for review
arporter Dec 6, 2023
f791adf
#418 remove missed line since #170 is closed.
arporter Jan 4, 2024
31117b8
#418 update copyright date
arporter Jan 4, 2024
e4513e5
Merge remote-tracking branch 'origin/master' into 313_permit_intrinsi…
sergisiso Jan 25, 2024
f7ebb67
#418 Update changelog
sergisiso Jan 25, 2024
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Modifications by (in alphabetical order):
* P. Vitt, University of Siegen, Germany
* A. Voysey, UK Met Office

25/01/2024 PR #418 for #313. Allow intrinsic shadowing and improve fparser symbol table.

11/01/2024 PR #439 for #432. Fix RTD build and clean up setuptools config.

03/10/2023 PR #431 for #430. Fixes bug in WHERE handling in fparser1.
Expand Down
1 change: 1 addition & 0 deletions doc/source/developers_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ corresponding dictionary entries are instances of the `SymbolTable`
class:

.. autoclass:: fparser.two.symbol_table.SymbolTable
:members:

The entries in these tables are instances of the named tuple,
`SymbolTable.Symbol` which currently has the properties:
Expand Down
136 changes: 72 additions & 64 deletions src/fparser/two/Fortran2003.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python

# Modified work Copyright (c) 2017-2023 Science and Technology
# Modified work Copyright (c) 2017-2024 Science and Technology
# Facilities Council.
# Original work Copyright (c) 1999-2008 Pearu Peterson

Expand Down Expand Up @@ -12333,77 +12333,85 @@ def match(string):

:param str string: the string to match with the pattern rule.

:return: a tuple of size 2 containing the name of the \
intrinsic and its arguments if there is a match, or None if \
there is not.
:rtype: (:py:class:`fparser.two.Fortran2003.Intrinsic_Name`, \
:py:class:`fparser.two.Fortran2003.Actual_Arg_Spec_List`) or \
NoneType
:return: a tuple of size 2 containing the name of the intrinsic
and its arguments if there is a match, or None if there is not.
:rtype: Tuple[:py:class:`fparser.two.Fortran2003.Intrinsic_Name`,
:py:class:`fparser.two.Fortran2003.Actual_Arg_Spec_List`] | NoneType

:raises InternalSyntaxError: If the number of arguments \
provided does not match the number of arguments expected by \
the intrinsic.
:raises InternalSyntaxError: If the number of arguments provided does
not match the number of arguments expected by the intrinsic and
there are no wildcard imports that could be bringing a routine
(that overrides it) into scope.

"""
result = CallBase.match(Intrinsic_Name, Actual_Arg_Spec_List, string)
if result:
# There is a match so check the number of args provided
# matches the number of args expected by the intrinsic.
function_name = str(result[0])
function_args = result[1]
if not result:
return None

# Check that that this name is not being shadowed (i.e. overridden)
# by a symbol in scope at this point.
table = SYMBOL_TABLES.current_scope
try:
table.lookup(function_name)
# We found a matching name so refuse to match this intrinsic.
return None
except (KeyError, AttributeError):
# There is either no matching name in the table or we have
# no current scoping region.
pass

# This if/else will not be needed once issue #170 has been
# addressed.
if isinstance(function_args, Actual_Arg_Spec_List):
nargs = len(function_args.items)
elif function_args is None:
nargs = 0
else:
nargs = 1
# There is a match so check the number of args provided
# matches the number of args expected by the intrinsic.
function_name = str(result[0])
function_args = result[1]

# Check that that this name is not being shadowed (i.e. overridden)
# by a symbol in scope at this point.
table = SYMBOL_TABLES.current_scope
try:
table.lookup(function_name)
# We found a matching name so refuse to match this intrinsic.
return None
except (KeyError, AttributeError):
# There is either no matching name in the table or we have
# no current scoping region.
pass

nargs = 0 if function_args is None else len(function_args.items)

if function_name in Intrinsic_Name.specific_function_names.keys():
# If this is a specific function then use its generic
# name to test min and max number of arguments.
test_name = Intrinsic_Name.specific_function_names[function_name]
else:
test_name = function_name

min_nargs = Intrinsic_Name.generic_function_names[test_name]["min"]
max_nargs = Intrinsic_Name.generic_function_names[test_name]["max"]

# None indicates an unlimited number of arguments
if max_nargs is None:
if nargs < min_nargs:
if table and not table.all_symbols_resolved:
# Wrong number of arguments to be an intrinsic so it must
# be a call to a routine being brought into scope from
# elsewhere.
return None

if function_name in Intrinsic_Name.specific_function_names.keys():
# If this is a specific function then use its generic
# name to test min and max number of arguments.
test_name = Intrinsic_Name.specific_function_names[function_name]
else:
test_name = function_name

min_nargs = Intrinsic_Name.generic_function_names[test_name]["min"]
max_nargs = Intrinsic_Name.generic_function_names[test_name]["max"]

if max_nargs is None:
if nargs < min_nargs:
# None indicates an unlimited number of arguments
raise InternalSyntaxError(
"Intrinsic '{0}' expects at least {1} args but found "
"{2}.".format(function_name, min_nargs, nargs)
)
# The number of arguments is valid. Return here as
# further tests will fail due to max_args being
# None.
return result
if min_nargs == max_nargs and nargs != min_nargs:
raise InternalSyntaxError(
"Intrinsic '{0}' expects {1} arg(s) but found {2}."
"".format(function_name, min_nargs, nargs)
)
if min_nargs < max_nargs and (nargs < min_nargs or nargs > max_nargs):
raise InternalSyntaxError(
"Intrinsic '{0}' expects between {1} and {2} args but "
"found {3}.".format(function_name, min_nargs, max_nargs, nargs)
"Intrinsic '{0}' expects at least {1} args but found "
"{2}.".format(function_name, min_nargs, nargs)
)
# The number of arguments is valid. Return here as
# further tests will fail due to max_args being
# None.
return result
if min_nargs == max_nargs and nargs != min_nargs:
if table and not table.all_symbols_resolved:
return None
raise InternalSyntaxError(
"Intrinsic '{0}' expects {1} arg(s) but found {2}."
"".format(function_name, min_nargs, nargs)
)
if min_nargs < max_nargs and (nargs < min_nargs or nargs > max_nargs):
if table and not table.all_symbols_resolved:
# Wrong number of arguments to be an intrinsic so it must
# be a call to a routine being brought into scope from
# elsewhere.
return None

raise InternalSyntaxError(
"Intrinsic '{0}' expects between {1} and {2} args but "
"found {3}.".format(function_name, min_nargs, max_nargs, nargs)
)
return result


Expand Down
Loading