Support Python 3.x kw-only arguments.

This commit is contained in:
Michael Hansen
2019-10-08 11:36:12 -07:00
parent 3e379c114e
commit 9309effba9
7 changed files with 102 additions and 20 deletions

View File

@@ -218,17 +218,20 @@ private:
class ASTFunction : public ASTNode {
public:
typedef std::list<PycRef<ASTNode> > defarg_t;
typedef std::list<PycRef<ASTNode>> defarg_t;
ASTFunction(PycRef<ASTNode> code, defarg_t defArgs)
: ASTNode(NODE_FUNCTION), m_code(code), m_defargs(defArgs) { }
ASTFunction(PycRef<ASTNode> code, defarg_t defArgs, defarg_t kwDefArgs)
: ASTNode(NODE_FUNCTION), m_code(std::move(code)),
m_defargs(std::move(defArgs)), m_kwdefargs(std::move(kwDefArgs)) { }
PycRef<ASTNode> code() const { return m_code; }
const defarg_t& defargs() const { return m_defargs; }
const defarg_t& kwdefargs() const { return m_kwdefargs; }
private:
PycRef<ASTNode> m_code;
defarg_t m_defargs;
defarg_t m_kwdefargs;
};

View File

@@ -258,7 +258,7 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
{
PycRef<ASTNode> fun_code = stack.top();
stack.pop();
stack.push(new ASTFunction(fun_code, ASTFunction::defarg_t()));
stack.push(new ASTFunction(fun_code, {}, {}));
}
break;
case Pyc::BUILD_LIST_A:
@@ -1350,12 +1350,18 @@ PycRef<ASTNode> BuildFromCode(PycRef<PycCode> code, PycModule* mod)
stack.pop();
}
ASTFunction::defarg_t defArgs;
for (int i=0; i<operand; i++) {
ASTFunction::defarg_t defArgs, kwDefArgs;
const int defCount = operand & 0xFF;
const int kwDefCount = (operand >> 8) & 0xFF;
for (int i = 0; i < defCount; ++i) {
defArgs.push_front(stack.top());
stack.pop();
}
stack.push(new ASTFunction(fun_code, defArgs));
for (int i = 0; i < kwDefCount; ++i) {
kwDefArgs.push_front(stack.top());
stack.pop();
}
stack.push(new ASTFunction(fun_code, defArgs, kwDefArgs));
}
break;
case Pyc::NOP:
@@ -2569,16 +2575,30 @@ void print_src(PycRef<ASTNode> node, PycModule* mod)
PycRef<ASTNode> code = node.cast<ASTFunction>()->code();
PycRef<PycCode> code_src = code.cast<ASTObject>()->object().cast<PycCode>();
ASTFunction::defarg_t defargs = node.cast<ASTFunction>()->defargs();
ASTFunction::defarg_t kwdefargs = node.cast<ASTFunction>()->kwdefargs();
auto da = defargs.cbegin();
int narg = 0;
for (int i=0; i<code_src->argCount(); i++) {
if (i > 0)
if (narg)
fputs(", ", pyc_output);
fprintf(pyc_output, "%s", code_src->getVarName(i)->value());
fprintf(pyc_output, "%s", code_src->getVarName(narg++)->value());
if ((code_src->argCount() - i) <= (int)defargs.size()) {
fputs(" = ", pyc_output);
print_src(*da++, mod);
}
}
da = kwdefargs.cbegin();
if (code_src->kwOnlyArgCount() != 0) {
fputs(narg == 0 ? "*" : ", *", pyc_output);
for (int i = 0; i < code_src->argCount(); i++) {
fputs(", ", pyc_output);
fprintf(pyc_output, "%s", code_src->getVarName(narg++)->value());
if ((code_src->kwOnlyArgCount() - i) <= (int)kwdefargs.size()) {
fputs(" = ", pyc_output);
print_src(*da++, mod);
}
}
}
fputs(": ", pyc_output);
inLambda = true;
@@ -2614,34 +2634,44 @@ void print_src(PycRef<ASTNode> node, PycModule* mod)
}
ASTFunction::defarg_t defargs = src.cast<ASTFunction>()->defargs();
ASTFunction::defarg_t kwdefargs = src.cast<ASTFunction>()->kwdefargs();
auto da = defargs.cbegin();
bool first = true;
for (int i=0; i<code_src->argCount(); i++) {
if (!first)
int narg = 0;
for (int i = 0; i < code_src->argCount(); ++i) {
if (narg)
fputs(", ", pyc_output);
fprintf(pyc_output, "%s", code_src->getVarName(i)->value());
fprintf(pyc_output, "%s", code_src->getVarName(narg++)->value());
if ((code_src->argCount() - i) <= (int)defargs.size()) {
fputs(" = ", pyc_output);
print_src(*da++, mod);
}
first = false;
}
da = kwdefargs.cbegin();
if (code_src->kwOnlyArgCount() != 0) {
fputs(narg == 0 ? "*" : ", *", pyc_output);
for (int i = 0; i < code_src->kwOnlyArgCount(); ++i) {
fputs(", ", pyc_output);
fprintf(pyc_output, "%s", code_src->getVarName(narg++)->value());
if ((code_src->kwOnlyArgCount() - i) <= (int)kwdefargs.size()) {
fputs(" = ", pyc_output);
print_src(*da++, mod);
}
}
}
if (code_src->flags() & PycCode::CO_VARARGS) {
if (!first)
if (narg)
fputs(", ", pyc_output);
fprintf(pyc_output, "*%s", code_src->getVarName(code_src->argCount())->value());
first = false;
fprintf(pyc_output, "*%s", code_src->getVarName(narg++)->value());
}
if (code_src->flags() & PycCode::CO_VARKEYWORDS) {
if (!first)
if (narg)
fputs(", ", pyc_output);
int idx = code_src->argCount();
if (code_src->flags() & PycCode::CO_VARARGS) {
idx++;
}
fprintf(pyc_output, "**%s", code_src->getVarName(idx)->value());
first = false;
fprintf(pyc_output, "**%s", code_src->getVarName(narg++)->value());
}
if (isLambda) {

View File

@@ -24,3 +24,36 @@ def x4b(foo, bar = 1, bla = 2, **kwargs):
def x4c(foo, bar = 1, bla = 2, *args, **kwargs):
pass
def x5a(*, bar):
pass
def x5b(*, bar = 1):
pass
def x5c(*, bar = 1, **kwargs):
pass
def x6a(foo, *, bar):
pass
def x6b(foo, *, bar = 1):
pass
def x6c(foo = 1, *, bar):
pass
def x6d(foo = 1, *, bar = 2):
pass
def x7a(foo, *, bar, **kwargs):
pass
def x7b(foo, *, bar = 1, **kwargs):
pass
def x7c(foo = 1, *, bar, **kwargs):
pass
def x7d(foo = 1, *, bar = 2, **kwargs):
pass

View File

@@ -33,3 +33,19 @@ pass <EOL>
def x4c ( foo , bar = 1 , bla = 2 , * args , ** kwargs ) : <EOL>
<INDENT>
pass <EOL>
<OUTDENT>
def x5a ( * , bar = 1 ) : <EOL>
<INDENT>
pass <EOL>
<OUTDENT>
def x5b ( * , bar = 1 , ** kwargs ) : <EOL>
<INDENT>
pass <EOL>
<OUTDENT>
def x6a ( foo , * , bar = 1 ) : <EOL>
<INDENT>
pass <EOL>
<OUTDENT>
def x7a ( foo , * , bar = 1 , ** kwargs ) : <EOL>
<INDENT>
pass <EOL>