@@ -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