Commit 3f22811f authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

bpo-32892: Use ast.Constant instead of specific constant AST types. (GH-9445)

parent a94ee12c
...@@ -78,8 +78,8 @@ Node classes ...@@ -78,8 +78,8 @@ Node classes
node = ast.UnaryOp() node = ast.UnaryOp()
node.op = ast.USub() node.op = ast.USub()
node.operand = ast.Num() node.operand = ast.Constant()
node.operand.n = 5 node.operand.value = 5
node.operand.lineno = 0 node.operand.lineno = 0
node.operand.col_offset = 0 node.operand.col_offset = 0
node.lineno = 0 node.lineno = 0
...@@ -87,9 +87,16 @@ Node classes ...@@ -87,9 +87,16 @@ Node classes
or the more compact :: or the more compact ::
node = ast.UnaryOp(ast.USub(), ast.Num(5, lineno=0, col_offset=0), node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0),
lineno=0, col_offset=0) lineno=0, col_offset=0)
.. deprecated:: 3.8
Class :class:`ast.Constant` is now used for all constants. Old classes
:class:`ast.Num`, :class:`ast.Str`, :class:`ast.Bytes`,
:class:`ast.NameConstant` and :class:`ast.Ellipsis` are still available,
but they will be removed in future Python releases.
.. _abstract-grammar: .. _abstract-grammar:
...@@ -239,7 +246,7 @@ and classes for traversing abstract syntax trees: ...@@ -239,7 +246,7 @@ and classes for traversing abstract syntax trees:
def visit_Name(self, node): def visit_Name(self, node):
return copy_location(Subscript( return copy_location(Subscript(
value=Name(id='data', ctx=Load()), value=Name(id='data', ctx=Load()),
slice=Index(value=Str(s=node.id)), slice=Index(value=Constant(value=node.id)),
ctx=node.ctx ctx=node.ctx
), node) ), node)
......
...@@ -262,6 +262,11 @@ Deprecated ...@@ -262,6 +262,11 @@ Deprecated
(Contributed by Berker Peksag in :issue:`9372`.) (Contributed by Berker Peksag in :issue:`9372`.)
* :mod:`ast` classes ``Num``, ``Str``, ``Bytes``, ``NameConstant`` and
``Ellipsis`` are considered deprecated and will be removed in future Python
versions. :class:`~ast.Constant` should be used instead.
(Contributed by Serhiy Storchaka in :issue:`32892`.)
Removed Removed
======= =======
......
...@@ -208,11 +208,10 @@ enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4, ...@@ -208,11 +208,10 @@ enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4,
IfExp_kind=5, Dict_kind=6, Set_kind=7, ListComp_kind=8, IfExp_kind=5, Dict_kind=6, Set_kind=7, ListComp_kind=8,
SetComp_kind=9, DictComp_kind=10, GeneratorExp_kind=11, SetComp_kind=9, DictComp_kind=10, GeneratorExp_kind=11,
Await_kind=12, Yield_kind=13, YieldFrom_kind=14, Await_kind=12, Yield_kind=13, YieldFrom_kind=14,
Compare_kind=15, Call_kind=16, Num_kind=17, Str_kind=18, Compare_kind=15, Call_kind=16, FormattedValue_kind=17,
FormattedValue_kind=19, JoinedStr_kind=20, Bytes_kind=21, JoinedStr_kind=18, Constant_kind=19, Attribute_kind=20,
NameConstant_kind=22, Ellipsis_kind=23, Constant_kind=24, Subscript_kind=21, Starred_kind=22, Name_kind=23,
Attribute_kind=25, Subscript_kind=26, Starred_kind=27, List_kind=24, Tuple_kind=25};
Name_kind=28, List_kind=29, Tuple_kind=30};
struct _expr { struct _expr {
enum _expr_kind kind; enum _expr_kind kind;
union { union {
...@@ -297,14 +296,6 @@ struct _expr { ...@@ -297,14 +296,6 @@ struct _expr {
asdl_seq *keywords; asdl_seq *keywords;
} Call; } Call;
struct {
object n;
} Num;
struct {
string s;
} Str;
struct { struct {
expr_ty value; expr_ty value;
int conversion; int conversion;
...@@ -315,14 +306,6 @@ struct _expr { ...@@ -315,14 +306,6 @@ struct _expr {
asdl_seq *values; asdl_seq *values;
} JoinedStr; } JoinedStr;
struct {
bytes s;
} Bytes;
struct {
singleton value;
} NameConstant;
struct { struct {
constant value; constant value;
} Constant; } Constant;
...@@ -566,23 +549,12 @@ expr_ty _Py_Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators, ...@@ -566,23 +549,12 @@ expr_ty _Py_Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators,
#define Call(a0, a1, a2, a3, a4, a5) _Py_Call(a0, a1, a2, a3, a4, a5) #define Call(a0, a1, a2, a3, a4, a5) _Py_Call(a0, a1, a2, a3, a4, a5)
expr_ty _Py_Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, int expr_ty _Py_Call(expr_ty func, asdl_seq * args, asdl_seq * keywords, int
lineno, int col_offset, PyArena *arena); lineno, int col_offset, PyArena *arena);
#define Num(a0, a1, a2, a3) _Py_Num(a0, a1, a2, a3)
expr_ty _Py_Num(object n, int lineno, int col_offset, PyArena *arena);
#define Str(a0, a1, a2, a3) _Py_Str(a0, a1, a2, a3)
expr_ty _Py_Str(string s, int lineno, int col_offset, PyArena *arena);
#define FormattedValue(a0, a1, a2, a3, a4, a5) _Py_FormattedValue(a0, a1, a2, a3, a4, a5) #define FormattedValue(a0, a1, a2, a3, a4, a5) _Py_FormattedValue(a0, a1, a2, a3, a4, a5)
expr_ty _Py_FormattedValue(expr_ty value, int conversion, expr_ty format_spec, expr_ty _Py_FormattedValue(expr_ty value, int conversion, expr_ty format_spec,
int lineno, int col_offset, PyArena *arena); int lineno, int col_offset, PyArena *arena);
#define JoinedStr(a0, a1, a2, a3) _Py_JoinedStr(a0, a1, a2, a3) #define JoinedStr(a0, a1, a2, a3) _Py_JoinedStr(a0, a1, a2, a3)
expr_ty _Py_JoinedStr(asdl_seq * values, int lineno, int col_offset, PyArena expr_ty _Py_JoinedStr(asdl_seq * values, int lineno, int col_offset, PyArena
*arena); *arena);
#define Bytes(a0, a1, a2, a3) _Py_Bytes(a0, a1, a2, a3)
expr_ty _Py_Bytes(bytes s, int lineno, int col_offset, PyArena *arena);
#define NameConstant(a0, a1, a2, a3) _Py_NameConstant(a0, a1, a2, a3)
expr_ty _Py_NameConstant(singleton value, int lineno, int col_offset, PyArena
*arena);
#define Ellipsis(a0, a1, a2) _Py_Ellipsis(a0, a1, a2)
expr_ty _Py_Ellipsis(int lineno, int col_offset, PyArena *arena);
#define Constant(a0, a1, a2, a3) _Py_Constant(a0, a1, a2, a3) #define Constant(a0, a1, a2, a3) _Py_Constant(a0, a1, a2, a3)
expr_ty _Py_Constant(constant value, int lineno, int col_offset, PyArena expr_ty _Py_Constant(constant value, int lineno, int col_offset, PyArena
*arena); *arena);
......
...@@ -48,10 +48,8 @@ def literal_eval(node_or_string): ...@@ -48,10 +48,8 @@ def literal_eval(node_or_string):
node_or_string = node_or_string.body node_or_string = node_or_string.body
def _convert_num(node): def _convert_num(node):
if isinstance(node, Constant): if isinstance(node, Constant):
if isinstance(node.value, (int, float, complex)): if type(node.value) in (int, float, complex):
return node.value return node.value
elif isinstance(node, Num):
return node.n
raise ValueError('malformed node or string: ' + repr(node)) raise ValueError('malformed node or string: ' + repr(node))
def _convert_signed_num(node): def _convert_signed_num(node):
if isinstance(node, UnaryOp) and isinstance(node.op, (UAdd, USub)): if isinstance(node, UnaryOp) and isinstance(node.op, (UAdd, USub)):
...@@ -64,10 +62,6 @@ def literal_eval(node_or_string): ...@@ -64,10 +62,6 @@ def literal_eval(node_or_string):
def _convert(node): def _convert(node):
if isinstance(node, Constant): if isinstance(node, Constant):
return node.value return node.value
elif isinstance(node, (Str, Bytes)):
return node.s
elif isinstance(node, Num):
return node.n
elif isinstance(node, Tuple): elif isinstance(node, Tuple):
return tuple(map(_convert, node.elts)) return tuple(map(_convert, node.elts))
elif isinstance(node, List): elif isinstance(node, List):
...@@ -77,8 +71,6 @@ def literal_eval(node_or_string): ...@@ -77,8 +71,6 @@ def literal_eval(node_or_string):
elif isinstance(node, Dict): elif isinstance(node, Dict):
return dict(zip(map(_convert, node.keys), return dict(zip(map(_convert, node.keys),
map(_convert, node.values))) map(_convert, node.values)))
elif isinstance(node, NameConstant):
return node.value
elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)): elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)):
left = _convert_signed_num(node.left) left = _convert_signed_num(node.left)
right = _convert_num(node.right) right = _convert_num(node.right)
...@@ -329,3 +321,66 @@ class NodeTransformer(NodeVisitor): ...@@ -329,3 +321,66 @@ class NodeTransformer(NodeVisitor):
else: else:
setattr(node, field, new_node) setattr(node, field, new_node)
return node return node
# The following code is for backward compatibility.
# It will be removed in future.
def _getter(self):
return self.value
def _setter(self, value):
self.value = value
Constant.n = property(_getter, _setter)
Constant.s = property(_getter, _setter)
class _ABC(type):
def __instancecheck__(cls, inst):
if not isinstance(inst, Constant):
return False
if cls in _const_types:
try:
value = inst.value
except AttributeError:
return False
else:
return type(value) in _const_types[cls]
return type.__instancecheck__(cls, inst)
def _new(cls, *args, **kwargs):
if cls in _const_types:
return Constant(*args, **kwargs)
return Constant.__new__(cls, *args, **kwargs)
class Num(Constant, metaclass=_ABC):
_fields = ('n',)
__new__ = _new
class Str(Constant, metaclass=_ABC):
_fields = ('s',)
__new__ = _new
class Bytes(Constant, metaclass=_ABC):
_fields = ('s',)
__new__ = _new
class NameConstant(Constant, metaclass=_ABC):
__new__ = _new
class Ellipsis(Constant, metaclass=_ABC):
_fields = ()
def __new__(cls, *args, **kwargs):
if cls is Ellipsis:
return Constant(..., *args, **kwargs)
return Constant.__new__(cls, *args, **kwargs)
_const_types = {
Num: (int, float, complex),
Str: (str,),
Bytes: (bytes,),
NameConstant: (type(None), bool),
Ellipsis: (type(...),),
}
...@@ -2005,14 +2005,8 @@ def _signature_fromstr(cls, obj, s, skip_bound_arg=True): ...@@ -2005,14 +2005,8 @@ def _signature_fromstr(cls, obj, s, skip_bound_arg=True):
except NameError: except NameError:
raise RuntimeError() raise RuntimeError()
if isinstance(value, str): if isinstance(value, (str, int, float, bytes, bool, type(None))):
return ast.Str(value) return ast.Constant(value)
if isinstance(value, (int, float)):
return ast.Num(value)
if isinstance(value, bytes):
return ast.Bytes(value)
if value in (True, False, None):
return ast.NameConstant(value)
raise RuntimeError() raise RuntimeError()
class RewriteSymbolics(ast.NodeTransformer): class RewriteSymbolics(ast.NodeTransformer):
......
This diff is collapsed.
...@@ -116,9 +116,11 @@ f'eggs {a * x()} spam {b + y()}'""" ...@@ -116,9 +116,11 @@ f'eggs {a * x()} spam {b + y()}'"""
self.assertEqual(type(t.body[1]), ast.Expr) self.assertEqual(type(t.body[1]), ast.Expr)
self.assertEqual(type(t.body[1].value), ast.JoinedStr) self.assertEqual(type(t.body[1].value), ast.JoinedStr)
self.assertEqual(len(t.body[1].value.values), 4) self.assertEqual(len(t.body[1].value.values), 4)
self.assertEqual(type(t.body[1].value.values[0]), ast.Str) self.assertEqual(type(t.body[1].value.values[0]), ast.Constant)
self.assertEqual(type(t.body[1].value.values[0].value), str)
self.assertEqual(type(t.body[1].value.values[1]), ast.FormattedValue) self.assertEqual(type(t.body[1].value.values[1]), ast.FormattedValue)
self.assertEqual(type(t.body[1].value.values[2]), ast.Str) self.assertEqual(type(t.body[1].value.values[2]), ast.Constant)
self.assertEqual(type(t.body[1].value.values[2].value), str)
self.assertEqual(type(t.body[1].value.values[3]), ast.FormattedValue) self.assertEqual(type(t.body[1].value.values[3]), ast.FormattedValue)
self.assertEqual(t.body[1].lineno, 3) self.assertEqual(t.body[1].lineno, 3)
self.assertEqual(t.body[1].value.lineno, 3) self.assertEqual(t.body[1].value.lineno, 3)
...@@ -183,9 +185,11 @@ f'{a * f"-{x()}-"}'""" ...@@ -183,9 +185,11 @@ f'{a * f"-{x()}-"}'"""
self.assertEqual(binop.right.col_offset, 7) self.assertEqual(binop.right.col_offset, 7)
# check the nested call location # check the nested call location
self.assertEqual(len(binop.right.values), 3) self.assertEqual(len(binop.right.values), 3)
self.assertEqual(type(binop.right.values[0]), ast.Str) self.assertEqual(type(binop.right.values[0]), ast.Constant)
self.assertEqual(type(binop.right.values[0].value), str)
self.assertEqual(type(binop.right.values[1]), ast.FormattedValue) self.assertEqual(type(binop.right.values[1]), ast.FormattedValue)
self.assertEqual(type(binop.right.values[2]), ast.Str) self.assertEqual(type(binop.right.values[2]), ast.Constant)
self.assertEqual(type(binop.right.values[2].value), str)
self.assertEqual(binop.right.values[0].lineno, 3) self.assertEqual(binop.right.values[0].lineno, 3)
self.assertEqual(binop.right.values[1].lineno, 3) self.assertEqual(binop.right.values[1].lineno, 3)
self.assertEqual(binop.right.values[2].lineno, 3) self.assertEqual(binop.right.values[2].lineno, 3)
...@@ -215,9 +219,11 @@ f'{a * x()} {a * x()} {a * x()}' ...@@ -215,9 +219,11 @@ f'{a * x()} {a * x()} {a * x()}'
self.assertEqual(type(t.body[1].value), ast.JoinedStr) self.assertEqual(type(t.body[1].value), ast.JoinedStr)
self.assertEqual(len(t.body[1].value.values), 5) self.assertEqual(len(t.body[1].value.values), 5)
self.assertEqual(type(t.body[1].value.values[0]), ast.FormattedValue) self.assertEqual(type(t.body[1].value.values[0]), ast.FormattedValue)
self.assertEqual(type(t.body[1].value.values[1]), ast.Str) self.assertEqual(type(t.body[1].value.values[1]), ast.Constant)
self.assertEqual(type(t.body[1].value.values[1].value), str)
self.assertEqual(type(t.body[1].value.values[2]), ast.FormattedValue) self.assertEqual(type(t.body[1].value.values[2]), ast.FormattedValue)
self.assertEqual(type(t.body[1].value.values[3]), ast.Str) self.assertEqual(type(t.body[1].value.values[3]), ast.Constant)
self.assertEqual(type(t.body[1].value.values[3].value), str)
self.assertEqual(type(t.body[1].value.values[4]), ast.FormattedValue) self.assertEqual(type(t.body[1].value.values[4]), ast.FormattedValue)
self.assertEqual(t.body[1].lineno, 3) self.assertEqual(t.body[1].lineno, 3)
self.assertEqual(t.body[1].value.lineno, 3) self.assertEqual(t.body[1].value.lineno, 3)
...@@ -287,9 +293,11 @@ non-important content ...@@ -287,9 +293,11 @@ non-important content
self.assertEqual(type(t.body[1]), ast.Expr) self.assertEqual(type(t.body[1]), ast.Expr)
self.assertEqual(type(t.body[1].value), ast.JoinedStr) self.assertEqual(type(t.body[1].value), ast.JoinedStr)
self.assertEqual(len(t.body[1].value.values), 3) self.assertEqual(len(t.body[1].value.values), 3)
self.assertEqual(type(t.body[1].value.values[0]), ast.Str) self.assertEqual(type(t.body[1].value.values[0]), ast.Constant)
self.assertEqual(type(t.body[1].value.values[0].value), str)
self.assertEqual(type(t.body[1].value.values[1]), ast.FormattedValue) self.assertEqual(type(t.body[1].value.values[1]), ast.FormattedValue)
self.assertEqual(type(t.body[1].value.values[2]), ast.Str) self.assertEqual(type(t.body[1].value.values[2]), ast.Constant)
self.assertEqual(type(t.body[1].value.values[2].value), str)
# NOTE: the following invalid behavior is described in bpo-16806. # NOTE: the following invalid behavior is described in bpo-16806.
# - line number should be the *first* line (3), not the *last* (8) # - line number should be the *first* line (3), not the *last* (8)
# - column offset should not be -1 # - column offset should not be -1
......
...@@ -230,7 +230,7 @@ class AnnotationsFutureTestCase(unittest.TestCase): ...@@ -230,7 +230,7 @@ class AnnotationsFutureTestCase(unittest.TestCase):
eq("lukasz.langa.pl") eq("lukasz.langa.pl")
eq("call.me(maybe)") eq("call.me(maybe)")
eq("1 .real") eq("1 .real")
eq("1.0 .real") eq("1.0.real")
eq("....__class__") eq("....__class__")
eq("list[str]") eq("list[str]")
eq("dict[str, int]") eq("dict[str, int]")
......
...@@ -144,7 +144,8 @@ class PyclbrTest(TestCase): ...@@ -144,7 +144,8 @@ class PyclbrTest(TestCase):
def test_easy(self): def test_easy(self):
self.checkModule('pyclbr') self.checkModule('pyclbr')
self.checkModule('ast') # XXX: Metaclasses are not supported
# self.checkModule('ast')
self.checkModule('doctest', ignore=("TestResults", "_SpoofOut", self.checkModule('doctest', ignore=("TestResults", "_SpoofOut",
"DocTestCase", '_DocTestSuite')) "DocTestCase", '_DocTestSuite'))
self.checkModule('difflib', ignore=("Match",)) self.checkModule('difflib', ignore=("Match",))
......
The parser now represents all constants as :class:`ast.Constant` instead of
using specific constant AST types (``Num``, ``Str``, ``Bytes``,
``NameConstant`` and ``Ellipsis``). These classes are considered deprecated
and will be removed in future Python versions.
-- ASDL's 7 builtin types are: -- ASDL's 5 builtin types are:
-- identifier, int, string, bytes, object, singleton, constant -- identifier, int, string, object, constant
--
-- singleton: None, True or False
-- constant can be None, whereas None means "no value" for object.
module Python module Python
{ {
...@@ -75,13 +72,8 @@ module Python ...@@ -75,13 +72,8 @@ module Python
-- x < 4 < 3 and (x < 4) < 3 -- x < 4 < 3 and (x < 4) < 3
| Compare(expr left, cmpop* ops, expr* comparators) | Compare(expr left, cmpop* ops, expr* comparators)
| Call(expr func, expr* args, keyword* keywords) | Call(expr func, expr* args, keyword* keywords)
| Num(object n) -- a number as a PyObject.
| Str(string s) -- need to specify raw, unicode, etc?
| FormattedValue(expr value, int? conversion, expr? format_spec) | FormattedValue(expr value, int? conversion, expr? format_spec)
| JoinedStr(expr* values) | JoinedStr(expr* values)
| Bytes(bytes s)
| NameConstant(singleton value)
| Ellipsis
| Constant(constant value) | Constant(constant value)
-- the following expression can appear in assignment context -- the following expression can appear in assignment context
......
...@@ -855,17 +855,6 @@ static PyObject* ast2obj_int(long b) ...@@ -855,17 +855,6 @@ static PyObject* ast2obj_int(long b)
/* Conversion Python -> AST */ /* Conversion Python -> AST */
static int obj2ast_singleton(PyObject *obj, PyObject** out, PyArena* arena)
{
if (obj != Py_None && obj != Py_True && obj != Py_False) {
PyErr_SetString(PyExc_ValueError,
"AST singleton must be True, False, or None");
return 1;
}
*out = obj;
return 0;
}
static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena) static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena)
{ {
if (obj == Py_None) if (obj == Py_None)
...@@ -883,13 +872,11 @@ static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena) ...@@ -883,13 +872,11 @@ static int obj2ast_object(PyObject* obj, PyObject** out, PyArena* arena)
static int obj2ast_constant(PyObject* obj, PyObject** out, PyArena* arena) static int obj2ast_constant(PyObject* obj, PyObject** out, PyArena* arena)
{ {
if (obj) {
if (PyArena_AddPyObject(arena, obj) < 0) { if (PyArena_AddPyObject(arena, obj) < 0) {
*out = NULL; *out = NULL;
return -1; return -1;
} }
Py_INCREF(obj); Py_INCREF(obj);
}
*out = obj; *out = obj;
return 0; return 0;
} }
...@@ -903,24 +890,6 @@ static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena) ...@@ -903,24 +890,6 @@ static int obj2ast_identifier(PyObject* obj, PyObject** out, PyArena* arena)
return obj2ast_object(obj, out, arena); return obj2ast_object(obj, out, arena);
} }
static int obj2ast_string(PyObject* obj, PyObject** out, PyArena* arena)
{
if (!PyUnicode_CheckExact(obj) && !PyBytes_CheckExact(obj)) {
PyErr_SetString(PyExc_TypeError, "AST string must be of type str");
return 1;
}
return obj2ast_object(obj, out, arena);
}
static int obj2ast_bytes(PyObject* obj, PyObject** out, PyArena* arena)
{
if (!PyBytes_CheckExact(obj)) {
PyErr_SetString(PyExc_TypeError, "AST bytes must be of type bytes");
return 1;
}
return obj2ast_object(obj, out, arena);
}
static int obj2ast_int(PyObject* obj, int* out, PyArena* arena) static int obj2ast_int(PyObject* obj, int* out, PyArena* arena)
{ {
int i; int i;
......
This diff is collapsed.
...@@ -295,23 +295,6 @@ validate_expr(expr_ty exp, expr_context_ty ctx) ...@@ -295,23 +295,6 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
return 0; return 0;
} }
return 1; return 1;
case Num_kind: {
PyObject *n = exp->v.Num.n;
if (!PyLong_CheckExact(n) && !PyFloat_CheckExact(n) &&
!PyComplex_CheckExact(n)) {
PyErr_SetString(PyExc_TypeError, "non-numeric type in Num");
return 0;
}
return 1;
}
case Str_kind: {
PyObject *s = exp->v.Str.s;
if (!PyUnicode_CheckExact(s)) {
PyErr_SetString(PyExc_TypeError, "non-string type in Str");
return 0;
}
return 1;
}
case JoinedStr_kind: case JoinedStr_kind:
return validate_exprs(exp->v.JoinedStr.values, Load, 0); return validate_exprs(exp->v.JoinedStr.values, Load, 0);
case FormattedValue_kind: case FormattedValue_kind:
...@@ -320,14 +303,6 @@ validate_expr(expr_ty exp, expr_context_ty ctx) ...@@ -320,14 +303,6 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
if (exp->v.FormattedValue.format_spec) if (exp->v.FormattedValue.format_spec)
return validate_expr(exp->v.FormattedValue.format_spec, Load); return validate_expr(exp->v.FormattedValue.format_spec, Load);
return 1; return 1;
case Bytes_kind: {
PyObject *b = exp->v.Bytes.s;
if (!PyBytes_CheckExact(b)) {
PyErr_SetString(PyExc_TypeError, "non-bytes type in Bytes");
return 0;
}
return 1;
}
case Attribute_kind: case Attribute_kind:
return validate_expr(exp->v.Attribute.value, Load); return validate_expr(exp->v.Attribute.value, Load);
case Subscript_kind: case Subscript_kind:
...@@ -339,10 +314,8 @@ validate_expr(expr_ty exp, expr_context_ty ctx) ...@@ -339,10 +314,8 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
return validate_exprs(exp->v.List.elts, ctx, 0); return validate_exprs(exp->v.List.elts, ctx, 0);
case Tuple_kind: case Tuple_kind:
return validate_exprs(exp->v.Tuple.elts, ctx, 0); return validate_exprs(exp->v.Tuple.elts, ctx, 0);
/* These last cases don't have any checking. */ /* This last case doesn't have any checking. */
case Name_kind: case Name_kind:
case NameConstant_kind:
case Ellipsis_kind:
return 1; return 1;
default: default:
PyErr_SetString(PyExc_SystemError, "unexpected expression"); PyErr_SetString(PyExc_SystemError, "unexpected expression");
...@@ -1040,19 +1013,23 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) ...@@ -1040,19 +1013,23 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
break; break;
case Dict_kind: case Dict_kind:
case Set_kind: case Set_kind:
case Num_kind:
case Str_kind:
case Bytes_kind:
case JoinedStr_kind: case JoinedStr_kind:
case FormattedValue_kind: case FormattedValue_kind:
expr_name = "literal"; expr_name = "literal";
break; break;
case NameConstant_kind: case Constant_kind: {
PyObject *value = e->v.Constant.value;
if (value == Py_None || value == Py_False || value == Py_True) {
expr_name = "keyword"; expr_name = "keyword";
break; }
case Ellipsis_kind: else if (value == Py_Ellipsis) {
expr_name = "Ellipsis"; expr_name = "Ellipsis";
}
else {
expr_name = "literal";
}
break; break;
}
case Compare_kind: case Compare_kind:
expr_name = "comparison"; expr_name = "comparison";
break; break;
...@@ -2091,11 +2068,11 @@ ast_for_atom(struct compiling *c, const node *n) ...@@ -2091,11 +2068,11 @@ ast_for_atom(struct compiling *c, const node *n)
size_t len = strlen(s); size_t len = strlen(s);
if (len >= 4 && len <= 5) { if (len >= 4 && len <= 5) {
if (!strcmp(s, "None")) if (!strcmp(s, "None"))
return NameConstant(Py_None, LINENO(n), n->n_col_offset, c->c_arena); return Constant(Py_None, LINENO(n), n->n_col_offset, c->c_arena);
if (!strcmp(s, "True")) if (!strcmp(s, "True"))
return NameConstant(Py_True, LINENO(n), n->n_col_offset, c->c_arena); return Constant(Py_True, LINENO(n), n->n_col_offset, c->c_arena);
if (!strcmp(s, "False")) if (!strcmp(s, "False"))
return NameConstant(Py_False, LINENO(n), n->n_col_offset, c->c_arena); return Constant(Py_False, LINENO(n), n->n_col_offset, c->c_arena);
} }
name = new_identifier(s, c); name = new_identifier(s, c);
if (!name) if (!name)
...@@ -2144,10 +2121,10 @@ ast_for_atom(struct compiling *c, const node *n) ...@@ -2144,10 +2121,10 @@ ast_for_atom(struct compiling *c, const node *n)
Py_DECREF(pynum); Py_DECREF(pynum);
return NULL; return NULL;
} }
return Num(pynum, LINENO(n), n->n_col_offset, c->c_arena); return Constant(pynum, LINENO(n), n->n_col_offset, c->c_arena);
} }
case ELLIPSIS: /* Ellipsis */ case ELLIPSIS: /* Ellipsis */
return Ellipsis(LINENO(n), n->n_col_offset, c->c_arena); return Constant(Py_Ellipsis, LINENO(n), n->n_col_offset, c->c_arena);
case LPAR: /* some parenthesized expressions */ case LPAR: /* some parenthesized expressions */
ch = CHILD(n, 1); ch = CHILD(n, 1);
...@@ -4751,7 +4728,7 @@ typedef struct { ...@@ -4751,7 +4728,7 @@ typedef struct {
expr_ty's, and then after that start dynamically allocating, expr_ty's, and then after that start dynamically allocating,
doubling the number allocated each time. Note that the f-string doubling the number allocated each time. Note that the f-string
f'{0}a{1}' contains 3 expr_ty's: 2 FormattedValue's, and one f'{0}a{1}' contains 3 expr_ty's: 2 FormattedValue's, and one
Str for the literal 'a'. So you add expr_ty's about twice as Constant for the literal 'a'. So you add expr_ty's about twice as
fast as you add exressions in an f-string. */ fast as you add exressions in an f-string. */
Py_ssize_t allocated; /* Number we've allocated. */ Py_ssize_t allocated; /* Number we've allocated. */
...@@ -4903,7 +4880,7 @@ FstringParser_Dealloc(FstringParser *state) ...@@ -4903,7 +4880,7 @@ FstringParser_Dealloc(FstringParser *state)
ExprList_Dealloc(&state->expr_list); ExprList_Dealloc(&state->expr_list);
} }
/* Make a Str node, but decref the PyUnicode object being added. */ /* Make a Constant node, but decref the PyUnicode object being added. */
static expr_ty static expr_ty
make_str_node_and_del(PyObject **str, struct compiling *c, const node* n) make_str_node_and_del(PyObject **str, struct compiling *c, const node* n)
{ {
...@@ -4914,7 +4891,7 @@ make_str_node_and_del(PyObject **str, struct compiling *c, const node* n) ...@@ -4914,7 +4891,7 @@ make_str_node_and_del(PyObject **str, struct compiling *c, const node* n)
Py_DECREF(s); Py_DECREF(s);
return NULL; return NULL;
} }
return Str(s, LINENO(n), n->n_col_offset, c->c_arena); return Constant(s, LINENO(n), n->n_col_offset, c->c_arena);
} }
/* Add a non-f-string (that is, a regular literal string). str is /* Add a non-f-string (that is, a regular literal string). str is
...@@ -5002,11 +4979,11 @@ FstringParser_ConcatFstring(FstringParser *state, const char **str, ...@@ -5002,11 +4979,11 @@ FstringParser_ConcatFstring(FstringParser *state, const char **str,
break; break;
/* We know we have an expression. Convert any existing string /* We know we have an expression. Convert any existing string
to a Str node. */ to a Constant node. */
if (!state->last_str) { if (!state->last_str) {
/* Do nothing. No previous literal. */ /* Do nothing. No previous literal. */
} else { } else {
/* Convert the existing last_str literal to a Str node. */ /* Convert the existing last_str literal to a Constant node. */
expr_ty str = make_str_node_and_del(&state->last_str, c, n); expr_ty str = make_str_node_and_del(&state->last_str, c, n);
if (!str || ExprList_Append(&state->expr_list, str) < 0) if (!str || ExprList_Append(&state->expr_list, str) < 0)
return -1; return -1;
...@@ -5033,7 +5010,7 @@ FstringParser_ConcatFstring(FstringParser *state, const char **str, ...@@ -5033,7 +5010,7 @@ FstringParser_ConcatFstring(FstringParser *state, const char **str,
} }
/* Convert the partial state reflected in last_str and expr_list to an /* Convert the partial state reflected in last_str and expr_list to an
expr_ty. The expr_ty can be a Str, or a JoinedStr. */ expr_ty. The expr_ty can be a Constant, or a JoinedStr. */
static expr_ty static expr_ty
FstringParser_Finish(FstringParser *state, struct compiling *c, FstringParser_Finish(FstringParser *state, struct compiling *c,
const node *n) const node *n)
...@@ -5055,7 +5032,7 @@ FstringParser_Finish(FstringParser *state, struct compiling *c, ...@@ -5055,7 +5032,7 @@ FstringParser_Finish(FstringParser *state, struct compiling *c,
return make_str_node_and_del(&state->last_str, c, n); return make_str_node_and_del(&state->last_str, c, n);
} }
/* Create a Str node out of last_str, if needed. It will be the /* Create a Constant node out of last_str, if needed. It will be the
last node in our expression list. */ last node in our expression list. */
if (state->last_str) { if (state->last_str) {
expr_ty str = make_str_node_and_del(&state->last_str, c, n); expr_ty str = make_str_node_and_del(&state->last_str, c, n);
...@@ -5206,9 +5183,9 @@ parsestr(struct compiling *c, const node *n, int *bytesmode, int *rawmode, ...@@ -5206,9 +5183,9 @@ parsestr(struct compiling *c, const node *n, int *bytesmode, int *rawmode,
/* Accepts a STRING+ atom, and produces an expr_ty node. Run through /* Accepts a STRING+ atom, and produces an expr_ty node. Run through
each STRING atom, and process it as needed. For bytes, just each STRING atom, and process it as needed. For bytes, just
concatenate them together, and the result will be a Bytes node. For concatenate them together, and the result will be a Constant node. For
normal strings and f-strings, concatenate them together. The result normal strings and f-strings, concatenate them together. The result
will be a Str node if there were no f-strings; a FormattedValue will be a Constant node if there were no f-strings; a FormattedValue
node if there's just an f-string (with no leading or trailing node if there's just an f-string (with no leading or trailing
literals), or a JoinedStr node if there are multiple f-strings or literals), or a JoinedStr node if there are multiple f-strings or
any literals involved. */ any literals involved. */
...@@ -5279,7 +5256,7 @@ parsestrplus(struct compiling *c, const node *n) ...@@ -5279,7 +5256,7 @@ parsestrplus(struct compiling *c, const node *n)
/* Just return the bytes object and we're done. */ /* Just return the bytes object and we're done. */
if (PyArena_AddPyObject(c->c_arena, bytes_str) < 0) if (PyArena_AddPyObject(c->c_arena, bytes_str) < 0)
goto error; goto error;
return Bytes(bytes_str, LINENO(n), n->n_col_offset, c->c_arena); return Constant(bytes_str, LINENO(n), n->n_col_offset, c->c_arena);
} }
/* We're not a bytes string, bytes_str should never have been set. */ /* We're not a bytes string, bytes_str should never have been set. */
...@@ -5304,9 +5281,6 @@ _PyAST_GetDocString(asdl_seq *body) ...@@ -5304,9 +5281,6 @@ _PyAST_GetDocString(asdl_seq *body)
return NULL; return NULL;
} }
expr_ty e = st->v.Expr.value; expr_ty e = st->v.Expr.value;
if (e->kind == Str_kind) {
return e->v.Str.s;
}
if (e->kind == Constant_kind && PyUnicode_CheckExact(e->v.Constant.value)) { if (e->kind == Constant_kind && PyUnicode_CheckExact(e->v.Constant.value)) {
return e->v.Constant.value; return e->v.Constant.value;
} }
......
...@@ -5,47 +5,6 @@ ...@@ -5,47 +5,6 @@
#include "ast.h" #include "ast.h"
/* TODO: is_const and get_const_value are copied from Python/compile.c.
It should be deduped in the future. Maybe, we can include this file
from compile.c?
*/
static int
is_const(expr_ty e)
{
switch (e->kind) {
case Constant_kind:
case Num_kind:
case Str_kind:
case Bytes_kind:
case Ellipsis_kind:
case NameConstant_kind:
return 1;
default:
return 0;
}
}
static PyObject *
get_const_value(expr_ty e)
{
switch (e->kind) {
case Constant_kind:
return e->v.Constant.value;
case Num_kind:
return e->v.Num.n;
case Str_kind:
return e->v.Str.s;
case Bytes_kind:
return e->v.Bytes.s;
case Ellipsis_kind:
return Py_Ellipsis;
case NameConstant_kind:
return e->v.NameConstant.value;
default:
Py_UNREACHABLE();
}
}
static int static int
make_const(expr_ty node, PyObject *val, PyArena *arena) make_const(expr_ty node, PyObject *val, PyArena *arena)
{ {
...@@ -81,7 +40,7 @@ fold_unaryop(expr_ty node, PyArena *arena, int optimize) ...@@ -81,7 +40,7 @@ fold_unaryop(expr_ty node, PyArena *arena, int optimize)
{ {
expr_ty arg = node->v.UnaryOp.operand; expr_ty arg = node->v.UnaryOp.operand;
if (!is_const(arg)) { if (arg->kind != Constant_kind) {
/* Fold not into comparison */ /* Fold not into comparison */
if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind && if (node->v.UnaryOp.op == Not && arg->kind == Compare_kind &&
asdl_seq_LEN(arg->v.Compare.ops) == 1) { asdl_seq_LEN(arg->v.Compare.ops) == 1) {
...@@ -123,7 +82,7 @@ fold_unaryop(expr_ty node, PyArena *arena, int optimize) ...@@ -123,7 +82,7 @@ fold_unaryop(expr_ty node, PyArena *arena, int optimize)
[UAdd] = PyNumber_Positive, [UAdd] = PyNumber_Positive,
[USub] = PyNumber_Negative, [USub] = PyNumber_Negative,
}; };
PyObject *newval = ops[node->v.UnaryOp.op](get_const_value(arg)); PyObject *newval = ops[node->v.UnaryOp.op](arg->v.Constant.value);
return make_const(node, newval, arena); return make_const(node, newval, arena);
} }
...@@ -259,12 +218,12 @@ fold_binop(expr_ty node, PyArena *arena, int optimize) ...@@ -259,12 +218,12 @@ fold_binop(expr_ty node, PyArena *arena, int optimize)
expr_ty lhs, rhs; expr_ty lhs, rhs;
lhs = node->v.BinOp.left; lhs = node->v.BinOp.left;
rhs = node->v.BinOp.right; rhs = node->v.BinOp.right;
if (!is_const(lhs) || !is_const(rhs)) { if (lhs->kind != Constant_kind || rhs->kind != Constant_kind) {
return 1; return 1;
} }
PyObject *lv = get_const_value(lhs); PyObject *lv = lhs->v.Constant.value;
PyObject *rv = get_const_value(rhs); PyObject *rv = rhs->v.Constant.value;
PyObject *newval; PyObject *newval;
switch (node->v.BinOp.op) { switch (node->v.BinOp.op) {
...@@ -316,7 +275,7 @@ make_const_tuple(asdl_seq *elts) ...@@ -316,7 +275,7 @@ make_const_tuple(asdl_seq *elts)
{ {
for (int i = 0; i < asdl_seq_LEN(elts); i++) { for (int i = 0; i < asdl_seq_LEN(elts); i++) {
expr_ty e = (expr_ty)asdl_seq_GET(elts, i); expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
if (!is_const(e)) { if (e->kind != Constant_kind) {
return NULL; return NULL;
} }
} }
...@@ -328,7 +287,7 @@ make_const_tuple(asdl_seq *elts) ...@@ -328,7 +287,7 @@ make_const_tuple(asdl_seq *elts)
for (int i = 0; i < asdl_seq_LEN(elts); i++) { for (int i = 0; i < asdl_seq_LEN(elts); i++) {
expr_ty e = (expr_ty)asdl_seq_GET(elts, i); expr_ty e = (expr_ty)asdl_seq_GET(elts, i);
PyObject *v = get_const_value(e); PyObject *v = e->v.Constant.value;
Py_INCREF(v); Py_INCREF(v);
PyTuple_SET_ITEM(newval, i, v); PyTuple_SET_ITEM(newval, i, v);
} }
...@@ -357,16 +316,16 @@ fold_subscr(expr_ty node, PyArena *arena, int optimize) ...@@ -357,16 +316,16 @@ fold_subscr(expr_ty node, PyArena *arena, int optimize)
arg = node->v.Subscript.value; arg = node->v.Subscript.value;
slice = node->v.Subscript.slice; slice = node->v.Subscript.slice;
if (node->v.Subscript.ctx != Load || if (node->v.Subscript.ctx != Load ||
!is_const(arg) || arg->kind != Constant_kind ||
/* TODO: handle other types of slices */ /* TODO: handle other types of slices */
slice->kind != Index_kind || slice->kind != Index_kind ||
!is_const(slice->v.Index.value)) slice->v.Index.value->kind != Constant_kind)
{ {
return 1; return 1;
} }
idx = slice->v.Index.value; idx = slice->v.Index.value;
newval = PyObject_GetItem(get_const_value(arg), get_const_value(idx)); newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value);
return make_const(node, newval, arena); return make_const(node, newval, arena);
} }
......
...@@ -567,8 +567,6 @@ append_fstring_element(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) ...@@ -567,8 +567,6 @@ append_fstring_element(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
switch (e->kind) { switch (e->kind) {
case Constant_kind: case Constant_kind:
return append_fstring_unicode(writer, e->v.Constant.value); return append_fstring_unicode(writer, e->v.Constant.value);
case Str_kind:
return append_fstring_unicode(writer, e->v.Str.s);
case JoinedStr_kind: case JoinedStr_kind:
return append_joinedstr(writer, e, is_format_spec); return append_joinedstr(writer, e, is_format_spec);
case FormattedValue_kind: case FormattedValue_kind:
...@@ -690,13 +688,12 @@ static int ...@@ -690,13 +688,12 @@ static int
append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e) append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e)
{ {
const char *period; const char *period;
APPEND_EXPR(e->v.Attribute.value, PR_ATOM); expr_ty v = e->v.Attribute.value;
APPEND_EXPR(v, PR_ATOM);
/* Special case: integers require a space for attribute access to be /* Special case: integers require a space for attribute access to be
unambiguous. Floats and complex numbers don't but work with it, too. */ unambiguous. */
if (e->v.Attribute.value->kind == Num_kind || if (v->kind == Constant_kind && PyLong_CheckExact(v->v.Constant.value)) {
e->v.Attribute.value->kind == Constant_kind)
{
period = " ."; period = " .";
} }
else { else {
...@@ -841,21 +838,14 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level) ...@@ -841,21 +838,14 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level)
case Call_kind: case Call_kind:
return append_ast_call(writer, e); return append_ast_call(writer, e);
case Constant_kind: case Constant_kind:
if (e->v.Constant.value == Py_Ellipsis) {
APPEND_STR_FINISH("...");
}
return append_repr(writer, e->v.Constant.value); return append_repr(writer, e->v.Constant.value);
case Num_kind:
return append_repr(writer, e->v.Num.n);
case Str_kind:
return append_repr(writer, e->v.Str.s);
case JoinedStr_kind: case JoinedStr_kind:
return append_joinedstr(writer, e, false); return append_joinedstr(writer, e, false);
case FormattedValue_kind: case FormattedValue_kind:
return append_formattedvalue(writer, e, false); return append_formattedvalue(writer, e, false);
case Bytes_kind:
return append_repr(writer, e->v.Bytes.s);
case Ellipsis_kind:
APPEND_STR_FINISH("...");
case NameConstant_kind:
return append_repr(writer, e->v.NameConstant.value);
/* The following exprs can be assignment targets. */ /* The following exprs can be assignment targets. */
case Attribute_kind: case Attribute_kind:
return append_ast_attribute(writer, e); return append_ast_attribute(writer, e);
......
...@@ -1398,43 +1398,6 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) ...@@ -1398,43 +1398,6 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
} \ } \
} }
static int
is_const(expr_ty e)
{
switch (e->kind) {
case Constant_kind:
case Num_kind:
case Str_kind:
case Bytes_kind:
case Ellipsis_kind:
case NameConstant_kind:
return 1;
default:
return 0;
}
}
static PyObject *
get_const_value(expr_ty e)
{
switch (e->kind) {
case Constant_kind:
return e->v.Constant.value;
case Num_kind:
return e->v.Num.n;
case Str_kind:
return e->v.Str.s;
case Bytes_kind:
return e->v.Bytes.s;
case Ellipsis_kind:
return Py_Ellipsis;
case NameConstant_kind:
return e->v.NameConstant.value;
default:
Py_UNREACHABLE();
}
}
/* Search if variable annotations are present statically in a block. */ /* Search if variable annotations are present statically in a block. */
static int static int
...@@ -2568,7 +2531,7 @@ static int ...@@ -2568,7 +2531,7 @@ static int
compiler_return(struct compiler *c, stmt_ty s) compiler_return(struct compiler *c, stmt_ty s)
{ {
int preserve_tos = ((s->v.Return.value != NULL) && int preserve_tos = ((s->v.Return.value != NULL) &&
!is_const(s->v.Return.value)); (s->v.Return.value->kind != Constant_kind));
if (c->u->u_ste->ste_type != FunctionBlock) if (c->u->u_ste->ste_type != FunctionBlock)
return compiler_error(c, "'return' outside function"); return compiler_error(c, "'return' outside function");
if (s->v.Return.value != NULL && if (s->v.Return.value != NULL &&
...@@ -3054,7 +3017,7 @@ compiler_visit_stmt_expr(struct compiler *c, expr_ty value) ...@@ -3054,7 +3017,7 @@ compiler_visit_stmt_expr(struct compiler *c, expr_ty value)
return 1; return 1;
} }
if (is_const(value)) { if (value->kind == Constant_kind) {
/* ignore constant statement */ /* ignore constant statement */
return 1; return 1;
} }
...@@ -3502,7 +3465,7 @@ are_all_items_const(asdl_seq *seq, Py_ssize_t begin, Py_ssize_t end) ...@@ -3502,7 +3465,7 @@ are_all_items_const(asdl_seq *seq, Py_ssize_t begin, Py_ssize_t end)
Py_ssize_t i; Py_ssize_t i;
for (i = begin; i < end; i++) { for (i = begin; i < end; i++) {
expr_ty key = (expr_ty)asdl_seq_GET(seq, i); expr_ty key = (expr_ty)asdl_seq_GET(seq, i);
if (key == NULL || !is_const(key)) if (key == NULL || key->kind != Constant_kind)
return 0; return 0;
} }
return 1; return 1;
...@@ -3522,7 +3485,7 @@ compiler_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end ...@@ -3522,7 +3485,7 @@ compiler_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end
return 0; return 0;
} }
for (i = begin; i < end; i++) { for (i = begin; i < end; i++) {
key = get_const_value((expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); key = ((expr_ty)asdl_seq_GET(e->v.Dict.keys, i))->v.Constant.value;
Py_INCREF(key); Py_INCREF(key);
PyTuple_SET_ITEM(keys, i - begin, key); PyTuple_SET_ITEM(keys, i - begin, key);
} }
...@@ -4244,8 +4207,8 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) ...@@ -4244,8 +4207,8 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k)
static int static int
expr_constant(expr_ty e) expr_constant(expr_ty e)
{ {
if (is_const(e)) { if (e->kind == Constant_kind) {
return PyObject_IsTrue(get_const_value(e)); return PyObject_IsTrue(e->v.Constant.value);
} }
return -1; return -1;
} }
...@@ -4505,25 +4468,10 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) ...@@ -4505,25 +4468,10 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
case Constant_kind: case Constant_kind:
ADDOP_LOAD_CONST(c, e->v.Constant.value); ADDOP_LOAD_CONST(c, e->v.Constant.value);
break; break;
case Num_kind:
ADDOP_LOAD_CONST(c, e->v.Num.n);
break;
case Str_kind:
ADDOP_LOAD_CONST(c, e->v.Str.s);
break;
case JoinedStr_kind: case JoinedStr_kind:
return compiler_joined_str(c, e); return compiler_joined_str(c, e);
case FormattedValue_kind: case FormattedValue_kind:
return compiler_formatted_value(c, e); return compiler_formatted_value(c, e);
case Bytes_kind:
ADDOP_LOAD_CONST(c, e->v.Bytes.s);
break;
case Ellipsis_kind:
ADDOP_LOAD_CONST(c, Py_Ellipsis);
break;
case NameConstant_kind:
ADDOP_LOAD_CONST(c, e->v.NameConstant.value);
break;
/* The following exprs can be assignment targets. */ /* The following exprs can be assignment targets. */
case Attribute_kind: case Attribute_kind:
if (e->v.Attribute.ctx != AugStore) if (e->v.Attribute.ctx != AugStore)
......
...@@ -1461,11 +1461,6 @@ symtable_visit_expr(struct symtable *st, expr_ty e) ...@@ -1461,11 +1461,6 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
VISIT_SEQ(st, expr, e->v.JoinedStr.values); VISIT_SEQ(st, expr, e->v.JoinedStr.values);
break; break;
case Constant_kind: case Constant_kind:
case Num_kind:
case Str_kind:
case Bytes_kind:
case Ellipsis_kind:
case NameConstant_kind:
/* Nothing to do here. */ /* Nothing to do here. */
break; break;
/* The following exprs can be assignment targets. */ /* The following exprs can be assignment targets. */
......
...@@ -3840,9 +3840,6 @@ class DSLParser: ...@@ -3840,9 +3840,6 @@ class DSLParser:
# "starred": "a = [1, 2, 3]; *a" # "starred": "a = [1, 2, 3]; *a"
visit_Starred = bad_node visit_Starred = bad_node
# allow ellipsis, for now
# visit_Ellipsis = bad_node
blacklist = DetectBadNodes() blacklist = DetectBadNodes()
blacklist.visit(module) blacklist.visit(module)
bad = blacklist.bad bad = blacklist.bad
...@@ -3868,10 +3865,15 @@ class DSLParser: ...@@ -3868,10 +3865,15 @@ class DSLParser:
py_default = 'None' py_default = 'None'
c_default = "NULL" c_default = "NULL"
elif (isinstance(expr, ast.BinOp) or elif (isinstance(expr, ast.BinOp) or
(isinstance(expr, ast.UnaryOp) and not isinstance(expr.operand, ast.Num))): (isinstance(expr, ast.UnaryOp) and
not (isinstance(expr.operand, ast.Num) or
(hasattr(ast, 'Constant') and
isinstance(expr.operand, ast.Constant) and
type(expr.operand.value) in (int, float, complex)))
)):
c_default = kwargs.get("c_default") c_default = kwargs.get("c_default")
if not (isinstance(c_default, str) and c_default): if not (isinstance(c_default, str) and c_default):
fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default.") fail("When you specify an expression (" + repr(default) + ") as your default value,\nyou MUST specify a valid c_default." + ast.dump(expr))
py_default = default py_default = default
value = unknown value = unknown
elif isinstance(expr, ast.Attribute): elif isinstance(expr, ast.Attribute):
...@@ -3946,6 +3948,11 @@ class DSLParser: ...@@ -3946,6 +3948,11 @@ class DSLParser:
self.function.parameters[parameter_name] = p self.function.parameters[parameter_name] = p
def parse_converter(self, annotation): def parse_converter(self, annotation):
if (hasattr(ast, 'Constant') and
isinstance(annotation, ast.Constant) and
type(annotation.value) is str):
return annotation.value, True, {}
if isinstance(annotation, ast.Str): if isinstance(annotation, ast.Str):
return annotation.s, True, {} return annotation.s, True, {}
......
...@@ -329,12 +329,6 @@ class Unparser: ...@@ -329,12 +329,6 @@ class Unparser:
self.leave() self.leave()
# expr # expr
def _Bytes(self, t):
self.write(repr(t.s))
def _Str(self, tree):
self.write(repr(tree.s))
def _JoinedStr(self, t): def _JoinedStr(self, t):
self.write("f") self.write("f")
string = io.StringIO() string = io.StringIO()
...@@ -352,10 +346,6 @@ class Unparser: ...@@ -352,10 +346,6 @@ class Unparser:
meth = getattr(self, "_fstring_" + type(value).__name__) meth = getattr(self, "_fstring_" + type(value).__name__)
meth(value, write) meth(value, write)
def _fstring_Str(self, t, write):
value = t.s.replace("{", "{{").replace("}", "}}")
write(value)
def _fstring_Constant(self, t, write): def _fstring_Constant(self, t, write):
assert isinstance(t.value, str) assert isinstance(t.value, str)
value = t.value.replace("{", "{{").replace("}", "}}") value = t.value.replace("{", "{{").replace("}", "}}")
...@@ -384,6 +374,7 @@ class Unparser: ...@@ -384,6 +374,7 @@ class Unparser:
def _write_constant(self, value): def _write_constant(self, value):
if isinstance(value, (float, complex)): if isinstance(value, (float, complex)):
# Substitute overflowing decimal literal for AST infinities.
self.write(repr(value).replace("inf", INFSTR)) self.write(repr(value).replace("inf", INFSTR))
else: else:
self.write(repr(value)) self.write(repr(value))
...@@ -398,16 +389,11 @@ class Unparser: ...@@ -398,16 +389,11 @@ class Unparser:
else: else:
interleave(lambda: self.write(", "), self._write_constant, value) interleave(lambda: self.write(", "), self._write_constant, value)
self.write(")") self.write(")")
elif value is ...:
self.write("...")
else: else:
self._write_constant(t.value) self._write_constant(t.value)
def _NameConstant(self, t):
self.write(repr(t.value))
def _Num(self, t):
# Substitute overflowing decimal literal for AST infinities.
self.write(repr(t.n).replace("inf", INFSTR))
def _List(self, t): def _List(self, t):
self.write("[") self.write("[")
interleave(lambda: self.write(", "), self.dispatch, t.elts) interleave(lambda: self.write(", "), self.dispatch, t.elts)
...@@ -539,8 +525,7 @@ class Unparser: ...@@ -539,8 +525,7 @@ class Unparser:
# Special case: 3.__abs__() is a syntax error, so if t.value # Special case: 3.__abs__() is a syntax error, so if t.value
# is an integer literal then we need to either parenthesize # is an integer literal then we need to either parenthesize
# it or add an extra space to get 3 .__abs__(). # it or add an extra space to get 3 .__abs__().
if ((isinstance(t.value, ast.Num) and isinstance(t.value.n, int)) if isinstance(t.value, ast.Constant) and isinstance(t.value.value, int):
or (isinstance(t.value, ast.Constant) and isinstance(t.value.value, int))):
self.write(" ") self.write(" ")
self.write(".") self.write(".")
self.write(t.attr) self.write(t.attr)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment