impl lambda

Update compiler.h
This commit is contained in:
blueloveTH 2022-11-08 22:05:18 +08:00
parent d78dfb9d7f
commit 56c2ef36db

View File

@ -337,7 +337,18 @@ public:
} }
void exprLambda() { void exprLambda() {
throw SyntaxError(path, parser->previous, "lambda is not implemented yet"); _Func func;
func.name = "<lambda>";
__compileFunctionArgs(func);
consume(TK(":"));
func.code = std::make_shared<CodeObject>();
func.code->co_name = func.name;
func.code->co_filename = path;
this->codes.push(func.code);
EXPR_TUPLE();
emitCode(OP_RETURN_VALUE);
this->codes.pop();
emitCode(OP_LOAD_CONST, getCode()->addConst(vm->PyFunction(func)));
} }
void exprAssign() { void exprAssign() {
@ -771,6 +782,38 @@ __LISTCOMP:
emitCode(OP_BUILD_CLASS, clsNameIdx); emitCode(OP_BUILD_CLASS, clsNameIdx);
} }
void __compileFunctionArgs(_Func& func){
int state = 0; // 0 for args, 1 for *args, 2 for k=v, 3 for **kwargs
do {
if(state == 3){
throw SyntaxError(path, parser->previous, "**kwargs should be the last argument");
}
matchNewLines();
if(match(TK("*"))){
if(state < 1) state = 1;
else throw SyntaxError(path, parser->previous, "*args should be placed before **kwargs");
}
else if(match(TK("**"))){
state = 3;
}
consume(TK("@id"));
const _Str& name = parser->previous.str();
if(func.hasName(name)) throw SyntaxError(path, parser->previous, "duplicate argument name");
if(state == 0 && peek() == TK("=")) state = 2;
switch (state)
{
case 0: func.args.push_back(name); break;
case 1: func.starredArg = name; state+=1; break;
case 2: consume(TK("=")); func.kwArgs[name] = consumeLiteral(); break;
case 3: func.doubleStarredArg = name; break;
}
} while (match(TK(",")));
}
void compileFunction(){ void compileFunction(){
if(isCompilingClass){ if(isCompilingClass){
if(match(TK("pass"))) return; if(match(TK("pass"))) return;
@ -781,35 +824,7 @@ __LISTCOMP:
func.name = parser->previous.str(); func.name = parser->previous.str();
if (match(TK("(")) && !match(TK(")"))) { if (match(TK("(")) && !match(TK(")"))) {
int state = 0; // 0 for args, 1 for *args, 2 for k=v, 3 for **kwargs __compileFunctionArgs(func);
do {
if(state == 3){
throw SyntaxError(path, parser->previous, "**kwargs should be the last argument");
}
matchNewLines();
if(match(TK("*"))){
if(state < 1) state = 1;
else throw SyntaxError(path, parser->previous, "*args should be placed before **kwargs");
}
else if(match(TK("**"))){
state = 3;
}
consume(TK("@id"));
const _Str& name = parser->previous.str();
if(func.hasName(name)) throw SyntaxError(path, parser->previous, "duplicate argument name");
if(state == 0 && peek() == TK("=")) state = 2;
switch (state)
{
case 0: func.args.push_back(name); break;
case 1: func.starredArg = name; state+=1; break;
case 2: consume(TK("=")); func.kwArgs[name] = consumeLiteral(); break;
case 3: func.doubleStarredArg = name; break;
}
} while (match(TK(",")));
consume(TK(")")); consume(TK(")"));
} }