Skip to content

Commit c42e009

Browse files
committed
Discard reference: use dedicated error instead of ENVAL
1 parent 7c78d83 commit c42e009

File tree

8 files changed

+38
-7
lines changed

8 files changed

+38
-7
lines changed

doc/1.4/language.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4064,6 +4064,7 @@ independent method callback(int i, void *aux) {
40644064
```
40654065

40664066
### The Discard Reference (`_`)
4067+
<a id="discard-reference"/>
40674068
```
40684069
_
40694070
```

py/dml/ast.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ def __setstate__(self, data):
5555
'default',
5656
'default_dml12',
5757
'delete',
58+
'discard',
5859
'dml',
5960
'dml_typedef',
6061
'dowhile',

py/dml/codegen.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,16 +1222,13 @@ def expr_variable(tree, location, scope):
12221222
if in_dev_tree:
12231223
e = in_dev_tree
12241224
if e is None:
1225-
# TODO/HACK: The discard ref is exposed like this to allow it to be as
1226-
# keyword-like as possible while still allowing it to be shadowed.
1227-
# Once we remove support for discard_ref_shadowing the discard ref
1228-
# should become a proper keyword and its codegen be done via dedicated
1229-
# dispatch
1230-
if name == '_' and tree.site.dml_version() != (1, 2):
1231-
return mkDiscardRef(tree.site)
12321225
raise EIDENT(tree.site, name)
12331226
return e
12341227

1228+
@expression_dispatcher
1229+
def expr_discard(tree, location, scope):
1230+
return mkDiscardRef(tree.site)
1231+
12351232
@expression_dispatcher
12361233
def expr_objectref(tree, location, scope):
12371234
[name] = tree.args

py/dml/ctree.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3597,6 +3597,9 @@ def __init__(self, site, type):
35973597
def __str__(self):
35983598
return '_'
35993599

3600+
def exc(self):
3601+
return EDISCARDREF(self.site)
3602+
36003603
def write(self, source):
36013604
if self.explicit_type:
36023605
return source.as_expr(self.type).discard(explicit=True)

py/dml/dmllex14.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,21 @@
1313

1414
tokens = (common_tokens
1515
+ ('HASHCONDOP', 'HASHCOLON')
16+
+ ('DISCARD',)
1617
+ tuple(hashids.values()))
1718

1819
t_HASHCONDOP = r'\#\?'
1920
t_HASHCOLON = r'\#:'
21+
t_DISCARD = r'_'
2022

2123
keywords_dml14 = dict(keywords_common)
2224
for kw in ['param', 'saved', 'async', 'await', 'with', 'shared', 'stringify',
2325
'export', 'as', 'independent', 'startup', 'memoized', 'hook']:
2426
keywords_dml14[kw] = kw.upper()
2527
tokens += (kw.upper(),)
2628

29+
keywords_dml14['_'] = 'DISCARD'
30+
2731
reserved_idents = reserved_idents_common + (
2832
'PARAM', 'SAVED', 'INDEPENDENT', 'STARTUP', 'MEMOIZED')
2933

py/dml/dmlparse.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1801,6 +1801,11 @@ def expression_ident(t):
18011801
| DEFAULT'''
18021802
t[0] = ast.variable(site(t), t[1])
18031803

1804+
@prod_dml14
1805+
def expression_discardref(t):
1806+
'''expression : discard'''
1807+
t[0] = t[1]
1808+
18041809
@prod_dml14
18051810
def expression_this(t):
18061811
'''expression : THIS'''
@@ -2660,6 +2665,11 @@ def objident(t):
26602665
| REGISTER'''
26612666
t[0] = t[1]
26622667

2668+
@prod_dml14
2669+
def discard(t):
2670+
'discard : DISCARD'
2671+
t[0] = ast.discard(site(t, 1))
2672+
26632673
def ident_rule(idents):
26642674
return 'ident : ' + "\n| ".join(idents)
26652675

py/dml/messages.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,6 +1893,16 @@ class EPRAGMA(DMLError):
18931893
"""
18941894
fmt = "Unknown pragma: %s"
18951895

1896+
class EDISCARDREF(DMLError):
1897+
"""
1898+
The expression *`_`* resolves to the [discard
1899+
reference](language.html#discard-reference), and can only be used as an
1900+
assignment target, in order to e.g. throw away return values of a function.
1901+
"""
1902+
version = "1.4"
1903+
fmt = ("'_' can only be used as an assignment target "
1904+
+ "(to discard some value)")
1905+
18961906
#
18971907
# WARNINGS (keep these as few as possible)
18981908
#

test/1.4/errors/T_ENVAL.dml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ method init() {
4646
b.r1;
4747
/// ERROR ENVAL
4848
b.r2.f;
49+
50+
/// ERROR EDISCARDREF
51+
_;
52+
// no error
53+
_ = true;
4954
}
5055

5156
// dev is not a value in 1.4. Need to capture this with a rather unnatural

0 commit comments

Comments
 (0)