in assignment works

This commit is contained in:
aps 2023-02-14 15:24:12 -05:00
parent 63a00d0faf
commit b66ef11dac
4 changed files with 88 additions and 21 deletions

View File

@ -74,6 +74,8 @@ public:
rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX }; rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX };
rules[TK("@fstr")] = { METHOD(exprFString), NO_INFIX }; rules[TK("@fstr")] = { METHOD(exprFString), NO_INFIX };
rules[TK("?")] = { nullptr, METHOD(exprTernary), PREC_TERNARY }; rules[TK("?")] = { nullptr, METHOD(exprTernary), PREC_TERNARY };
// do not include standalone, as it allows naked assignment
//rules[TK(":=")] = { nullptr, METHOD(exprWalrus), PREC_ASSIGNMENT };
rules[TK("=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT }; rules[TK("=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
rules[TK("+=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT }; rules[TK("+=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
rules[TK("-=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT }; rules[TK("-=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
@ -176,7 +178,7 @@ private:
} }
}catch(std::exception& _){ }catch(std::exception& _){
SyntaxError("invalid number literal"); SyntaxError("invalid number literal");
} }
} }
void lex_token(){ void lex_token(){
@ -201,12 +203,12 @@ private:
case '{': parser->set_next_token(TK("{")); return; case '{': parser->set_next_token(TK("{")); return;
case '}': parser->set_next_token(TK("}")); return; case '}': parser->set_next_token(TK("}")); return;
case ',': parser->set_next_token(TK(",")); return; case ',': parser->set_next_token(TK(",")); return;
case ':': parser->set_next_token(TK(":")); return;
case ';': parser->set_next_token(TK(";")); return; case ';': parser->set_next_token(TK(";")); return;
case '(': parser->set_next_token(TK("(")); return; case '(': parser->set_next_token(TK("(")); return;
case ')': parser->set_next_token(TK(")")); return; case ')': parser->set_next_token(TK(")")); return;
case '[': parser->set_next_token(TK("[")); return; case '[': parser->set_next_token(TK("[")); return;
case ']': parser->set_next_token(TK("]")); return; case ']': parser->set_next_token(TK("]")); return;
case ':': parser->set_next_token_2('=', TK(":"), TK(":=")); return;
case '%': parser->set_next_token_2('=', TK("%"), TK("%=")); return; case '%': parser->set_next_token_2('=', TK("%"), TK("%=")); return;
case '&': parser->set_next_token_2('=', TK("&"), TK("&=")); return; case '&': parser->set_next_token_2('=', TK("&"), TK("&=")); return;
case '|': parser->set_next_token_2('=', TK("|"), TK("|=")); return; case '|': parser->set_next_token_2('=', TK("|"), TK("|=")); return;
@ -283,7 +285,7 @@ private:
eat_number(); eat_number();
return; return;
} }
switch (parser->eat_name()) switch (parser->eat_name())
{ {
case 0: break; case 0: break;
@ -400,13 +402,21 @@ private:
emit(OP_LOAD_LAMBDA, co()->add_const(vm->PyFunction(func))); emit(OP_LOAD_LAMBDA, co()->add_const(vm->PyFunction(func)));
} }
void exprWalrus() {
// NAME is on stack
EXPR_TUPLE();
// EXPR is on stack
emit(OP_STORE_REF); // will pop the value and the name off the stack,
// we need to return the value now
}
void exprAssign() { void exprAssign() {
co()->_rvalue = true; co()->_rvalue = true;
TokenIndex op = parser->prev.type; TokenIndex op = parser->prev.type;
if(op == TK("=")) { // a = (expr) if(op == TK("=")) { // a = (expr)
EXPR_TUPLE(); EXPR_TUPLE();
emit(OP_STORE_REF); emit(OP_STORE_REF);
}else{ // a += (expr) -> a = a + (expr) }
else{ // a += (expr) -> a = a + (expr)
emit(OP_DUP_TOP); emit(OP_DUP_TOP);
EXPR(); EXPR();
switch (op) { switch (op) {
@ -502,8 +512,48 @@ private:
} }
void exprGrouping() { void exprGrouping() {
// either a expr in parens,
// or a tuple.
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
EXPR_TUPLE(); // do {
// if (peek() == TK("@id")) {
// consume(TK("@id"));
// exprAssign();
// }
// else {
// EXPR();
// }
// } while (match(TK(",")));
// EXPR_TUPLE();
do {
if (peek() == TK(")")) break;
if(peek() == TK("@id") && peek_next() == TK(":=")) {
consume(TK("@id"));
Token tkname = parser->prev;
int index = co()->add_name(
tkname.str(),
codes.size()>1 ? NAME_LOCAL : NAME_GLOBAL
);
emit(OP_LOAD_NAME_REF, index);
consume(TK(":="));
exprWalrus();
emit(OP_LOAD_NAME, index);
// const Str& key = parser->prev.str();
// emit(OP_LOAD_CONST, co()->add_const(vm->PyStr(key)));
// consume(TK("="));
// co()->_rvalue=true; EXPR(); co()->_rvalue=false;
}
else {
EXPR_TUPLE();
}
} while (match(TK(",")));
// if (peek() == TK("@id")) {
// consume(TK("@id"));
// exprAssign();
// } else {
// EXPR_TUPLE();
// }
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
consume(TK(")")); consume(TK(")"));
} }
@ -532,7 +582,7 @@ __LISTCOMP:
emit(OP_BUILD_LIST, 0); emit(OP_BUILD_LIST, 0);
EXPR_FOR_VARS();consume(TK("in"));EXPR_TUPLE(); EXPR_FOR_VARS();consume(TK("in"));EXPR_TUPLE();
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
int _skipPatch = emit(OP_JUMP_ABSOLUTE); int _skipPatch = emit(OP_JUMP_ABSOLUTE);
int _cond_start = co()->codes.size(); int _cond_start = co()->codes.size();
int _cond_end_return = -1; int _cond_end_return = -1;

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,21 @@
## Function Tests. ## Function Tests.
#a := 1
#_b = (1, 2)
#(d := 4) + 6
#(D := 4)
#assert D == 4
#x = D + 1
x = (a := 3,4)
y = (a := 3)
print(y)
#assert False # (D := 4)==4
# b = (d := 4) + (c := 4)
# c = (d := 2) + 1
# b = (x := a + 1) + 2
def f1(): def f1():
return 'f1' return 'f1'
assert f1() == 'f1' assert f1() == 'f1'
def f2(a, b, c, d): def f2(a, b, c, d):
return c return c
assert f2('a', 'b', 'c', 'd') == 'c' assert f2('a', 'b', 'c', 'd') == 'c'
def f3(a,b): def f3(a,b):
@ -15,7 +26,7 @@ def fact(n):
if n == 1: if n == 1:
return 1 return 1
return n * fact(n - 1) return n * fact(n - 1)
assert fact(5)==120 assert fact(5)==120
def f(a=1, b=-1): def f(a=1, b=-1):
return a + b return a + b

6
tests/_walrus.py Normal file
View File

@ -0,0 +1,6 @@
assert ( x := 1) == 1
assert ( y := 1) + 2 == 3
a = (y := 4) + 5
assert a == 9
assert y == 4