Skip to content

Commit db3a539

Browse files
authored
Extend MAKE_FUNCTION_A/MAKE_CLOSURE_A handling to support Python 3.0–3.14+
1 parent a05ddec commit db3a539

File tree

1 file changed

+111
-8
lines changed

1 file changed

+111
-8
lines changed

ASTree.cpp

Lines changed: 111 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,8 +1564,7 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
15641564
{
15651565
PycRef<ASTNode> fun_code = stack.top();
15661566
stack.pop();
1567-
1568-
/* Test for the qualified name of the function (at TOS) */
1567+
// Test for the qualified name of the function (at TOS)
15691568
int tos_type = fun_code.cast<ASTObject>()->object().type();
15701569
if (tos_type != PycObject::TYPE_CODE &&
15711570
tos_type != PycObject::TYPE_CODE2) {
@@ -1576,14 +1575,118 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
15761575
ASTFunction::defarg_t defArgs, kwDefArgs;
15771576
const int defCount = operand & 0xFF;
15781577
const int kwDefCount = (operand >> 8) & 0xFF;
1579-
for (int i = 0; i < defCount; ++i) {
1580-
defArgs.push_front(stack.top());
1581-
stack.pop();
1578+
const int annotationCount = (operand >> 16) & 0x7FFF;
1579+
1580+
// Python 3.3 and below
1581+
if (mod->verCompare(3, 3) <= 0) {
1582+
for (int i = 0; i < defCount; ++i) {
1583+
defArgs.push_front(stack.top());
1584+
stack.pop();
1585+
}
1586+
// KW Defaults not mentioned in docs, but they come after the positional args
1587+
for (int i = 0; i < kwDefCount; ++i) {
1588+
kwDefArgs.push_front(stack.top());
1589+
stack.pop(); // KW Pair object
1590+
stack.pop(); // KW Pair name
1591+
}
15821592
}
1583-
for (int i = 0; i < kwDefCount; ++i) {
1584-
kwDefArgs.push_front(stack.top());
1585-
stack.pop();
1593+
// Python 3.4-3.5
1594+
else if (mod->verCompare(3, 5) <= 0) {
1595+
// From Py 3.4: annotations and order change (kw first)
1596+
if (annotationCount) {
1597+
stack.pop(); // Tuple of param names for annotations
1598+
for (int i = 0; i < annotationCount; ++i) {
1599+
stack.pop(); // Pop annotation objects and ignore
1600+
}
1601+
}
1602+
for (int i = 0; i < kwDefCount; ++i) {
1603+
kwDefArgs.push_front(stack.top());
1604+
stack.pop(); // KW Pair object
1605+
stack.pop(); // KW Pair name
1606+
}
1607+
for (int i = 0; i < defCount; ++i) {
1608+
defArgs.push_front(stack.top());
1609+
stack.pop();
1610+
}
15861611
}
1612+
// Python 3.6-3.9 (flag mask, annotation dict)
1613+
else if (mod->verCompare(3, 9) <= 0) {
1614+
if (operand & 0x08) { // Cells for free vars to create a closure
1615+
stack.pop(); // Ignore these for syntax generation
1616+
}
1617+
if (operand & 0x04) { // Annotation dict (3.6-9)
1618+
stack.pop(); // Ignore annotations
1619+
}
1620+
if (operand & 0x02) { // Kwarg Defaults
1621+
PycRef<ASTNode> kw_tuple = stack.top();
1622+
stack.pop();
1623+
std::vector<PycRef<ASTNode>> kw_values = kw_tuple.cast<ASTConstMap>()->values();
1624+
for (const PycRef<ASTNode>& kw : kw_values) {
1625+
kwDefArgs.push_front(kw);
1626+
}
1627+
}
1628+
if (operand & 0x01) { // Positional Defaults (including positional-or-KW args)
1629+
PycRef<ASTNode> pos_tuple = stack.top();
1630+
stack.pop();
1631+
std::vector<PycRef<PycObject>> pos_values = pos_tuple.cast<ASTObject>()->object().cast<PycTuple>()->values();
1632+
for (const PycRef<PycObject>& pos : pos_values) {
1633+
defArgs.push_back(new ASTObject(pos));
1634+
}
1635+
}
1636+
}
1637+
// Python 3.10-3.13 (annotation can be dict or string, otherwise same)
1638+
else if (mod->verCompare(3, 13) <= 0) {
1639+
if (operand & 0x08) { // Cells for free vars to create a closure
1640+
stack.pop(); // Ignore these for syntax generation
1641+
}
1642+
if (operand & 0x04) { // Annotation dict (3.10-13) or string (PEP 563)
1643+
stack.pop(); // Ignore annotations
1644+
}
1645+
if (operand & 0x02) { // Kwarg Defaults
1646+
PycRef<ASTNode> kw_tuple = stack.top();
1647+
stack.pop();
1648+
std::vector<PycRef<ASTNode>> kw_values = kw_tuple.cast<ASTConstMap>()->values();
1649+
for (const PycRef<ASTNode>& kw : kw_values) {
1650+
kwDefArgs.push_front(kw);
1651+
}
1652+
}
1653+
if (operand & 0x01) { // Positional Defaults (including positional-or-KW args)
1654+
PycRef<ASTNode> pos_tuple = stack.top();
1655+
stack.pop();
1656+
std::vector<PycRef<PycObject>> pos_values = pos_tuple.cast<ASTObject>()->object().cast<PycTuple>()->values();
1657+
for (const PycRef<PycObject>& pos : pos_values) {
1658+
defArgs.push_back(new ASTObject(pos));
1659+
}
1660+
}
1661+
}
1662+
else {
1663+
if (operand & 0x10) {
1664+
stack.pop();
1665+
}
1666+
if (operand & 0x08) {
1667+
stack.pop();
1668+
}
1669+
if (operand & 0x04) {
1670+
stack.pop();
1671+
}
1672+
if (operand & 0x02) {
1673+
PycRef<ASTNode> kw_tuple = stack.top();
1674+
stack.pop();
1675+
std::vector<PycRef<ASTNode>> kw_values = kw_tuple.cast<ASTConstMap>()->values();
1676+
for (const PycRef<ASTNode>& kw : kw_values) {
1677+
kwDefArgs.push_front(kw);
1678+
}
1679+
}
1680+
if (operand & 0x01) {
1681+
PycRef<ASTNode> pos_tuple = stack.top();
1682+
stack.pop();
1683+
std::vector<PycRef<PycObject>> pos_values = pos_tuple.cast<ASTObject>()->object().cast<PycTuple>()->values();
1684+
for (const PycRef<PycObject>& pos : pos_values) {
1685+
defArgs.push_back(new ASTObject(pos));
1686+
}
1687+
}
1688+
}
1689+
15871690
stack.push(new ASTFunction(fun_code, defArgs, kwDefArgs));
15881691
}
15891692
break;

0 commit comments

Comments
 (0)