mirror of https://github.com/arendst/Tasmota.git
Berry `import strict` now detects useless expr without side effects (#18997)
This commit is contained in:
parent
eb655a4a8f
commit
34456e6193
|
@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
- Berry `bool( [] )` and `bool( {} )` now evaluate as `false` (#18986)
|
- Berry `bool( [] )` and `bool( {} )` now evaluate as `false` (#18986)
|
||||||
|
- Berry `import strict` now detects useless expr without side effects
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Matter support for temperature in Fahrenheit (`SetOption8 1`) (#18987)
|
- Matter support for temperature in Fahrenheit (`SetOption8 1`) (#18987)
|
||||||
|
|
|
@ -196,6 +196,7 @@ static void begin_block(bfuncinfo *finfo, bblockinfo *binfo, int type)
|
||||||
finfo->binfo = binfo; /* tell parser this is the current block */
|
finfo->binfo = binfo; /* tell parser this is the current block */
|
||||||
binfo->type = (bbyte)type;
|
binfo->type = (bbyte)type;
|
||||||
binfo->hasupval = 0;
|
binfo->hasupval = 0;
|
||||||
|
binfo->sideeffect = 0;
|
||||||
binfo->beginpc = finfo->pc; /* set starting pc for this block */
|
binfo->beginpc = finfo->pc; /* set starting pc for this block */
|
||||||
binfo->nactlocals = (bbyte)be_list_count(finfo->local); /* count number of local variables in previous block */
|
binfo->nactlocals = (bbyte)be_list_count(finfo->local); /* count number of local variables in previous block */
|
||||||
if (type & BLOCK_LOOP) {
|
if (type & BLOCK_LOOP) {
|
||||||
|
@ -796,6 +797,7 @@ static void call_expr(bparser *parser, bexpdesc *e)
|
||||||
int argc = 0, base;
|
int argc = 0, base;
|
||||||
int ismember = e->type == ETMEMBER;
|
int ismember = e->type == ETMEMBER;
|
||||||
|
|
||||||
|
parser->finfo->binfo->sideeffect = 1; /* has side effect */
|
||||||
/* func '(' [exprlist] ')' */
|
/* func '(' [exprlist] ')' */
|
||||||
check_var(parser, e);
|
check_var(parser, e);
|
||||||
/* code function index to next register */
|
/* code function index to next register */
|
||||||
|
@ -1030,11 +1032,13 @@ static void assign_expr(bparser *parser)
|
||||||
bexpdesc e;
|
bexpdesc e;
|
||||||
btokentype op;
|
btokentype op;
|
||||||
int line = parser->lexer.linenumber;
|
int line = parser->lexer.linenumber;
|
||||||
|
parser->finfo->binfo->sideeffect = 0; /* reinit side effect marker */
|
||||||
expr(parser, &e); /* left expression */
|
expr(parser, &e); /* left expression */
|
||||||
check_symbol(parser, &e);
|
check_symbol(parser, &e);
|
||||||
op = get_assign_op(parser);
|
op = get_assign_op(parser);
|
||||||
if (op != OP_NOT_ASSIGN) { /* assign operator */
|
if (op != OP_NOT_ASSIGN) { /* assign operator */
|
||||||
bexpdesc e1;
|
bexpdesc e1;
|
||||||
|
parser->finfo->binfo->sideeffect = 1;
|
||||||
scan_next_token(parser);
|
scan_next_token(parser);
|
||||||
compound_assign(parser, op, &e, &e1);
|
compound_assign(parser, op, &e, &e1);
|
||||||
if (check_newvar(parser, &e)) { /* new variable */
|
if (check_newvar(parser, &e)) { /* new variable */
|
||||||
|
@ -1110,6 +1114,9 @@ static void sub_expr(bparser *parser, bexpdesc *e, int prio)
|
||||||
check_var(parser, e); /* check that left part is valid */
|
check_var(parser, e); /* check that left part is valid */
|
||||||
scan_next_token(parser); /* move to next token */
|
scan_next_token(parser); /* move to next token */
|
||||||
be_code_prebinop(finfo, op, e); /* and or */
|
be_code_prebinop(finfo, op, e); /* and or */
|
||||||
|
if (op == OptConnect) {
|
||||||
|
parser->finfo->binfo->sideeffect = 1;
|
||||||
|
}
|
||||||
init_exp(&e2, ETVOID, 0);
|
init_exp(&e2, ETVOID, 0);
|
||||||
sub_expr(parser, &e2, binary_op_prio(op)); /* parse right side */
|
sub_expr(parser, &e2, binary_op_prio(op)); /* parse right side */
|
||||||
if ((e2.type == ETVOID) && (op == OptConnect)) {
|
if ((e2.type == ETVOID) && (op == OptConnect)) {
|
||||||
|
@ -1758,6 +1765,9 @@ static void throw_stmt(bparser *parser)
|
||||||
|
|
||||||
static void statement(bparser *parser)
|
static void statement(bparser *parser)
|
||||||
{
|
{
|
||||||
|
/* save value of sideeffect */
|
||||||
|
bbyte sideeffect = parser->finfo->binfo->sideeffect;
|
||||||
|
parser->finfo->binfo->sideeffect = 1; /* by default declare side effect */
|
||||||
switch (next_type(parser)) {
|
switch (next_type(parser)) {
|
||||||
case KeyIf: if_stmt(parser); break;
|
case KeyIf: if_stmt(parser); break;
|
||||||
case KeyWhile: while_stmt(parser); break;
|
case KeyWhile: while_stmt(parser); break;
|
||||||
|
@ -1772,8 +1782,16 @@ static void statement(bparser *parser)
|
||||||
case KeyVar: var_stmt(parser); break;
|
case KeyVar: var_stmt(parser); break;
|
||||||
case KeyTry: try_stmt(parser); break;
|
case KeyTry: try_stmt(parser); break;
|
||||||
case KeyRaise: throw_stmt(parser); break;
|
case KeyRaise: throw_stmt(parser); break;
|
||||||
case OptSemic: scan_next_token(parser); break; /* empty statement */
|
case OptSemic:
|
||||||
default: expr_stmt(parser); break;
|
parser->finfo->binfo->sideeffect = sideeffect; /* restore sideeffect */
|
||||||
|
scan_next_token(parser); break; /* empty statement */
|
||||||
|
default:
|
||||||
|
parser->finfo->binfo->sideeffect = sideeffect; /* restore sideeffect */
|
||||||
|
expr_stmt(parser);
|
||||||
|
if (comp_is_strict(parser->vm) && parser->finfo->binfo->sideeffect == 0) {
|
||||||
|
push_error(parser, "strict: expression without side effect detected");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
be_assert(parser->finfo->freereg >= be_list_count(parser->finfo->local));
|
be_assert(parser->finfo->freereg >= be_list_count(parser->finfo->local));
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ typedef struct bblockinfo {
|
||||||
bbyte nactlocals; /* number of active local variables */
|
bbyte nactlocals; /* number of active local variables */
|
||||||
bbyte type; /* block type mask */
|
bbyte type; /* block type mask */
|
||||||
bbyte hasupval; /* has upvalue mark */
|
bbyte hasupval; /* has upvalue mark */
|
||||||
|
bbyte sideeffect; /* did the last expr/statement had a side effect */
|
||||||
int breaklist; /* break list */
|
int breaklist; /* break list */
|
||||||
int beginpc; /* begin pc */
|
int beginpc; /* begin pc */
|
||||||
int continuelist; /* continue list */
|
int continuelist; /* continue list */
|
||||||
|
|
|
@ -111,7 +111,7 @@ class Persist
|
||||||
import json
|
import json
|
||||||
if isinstance(v, map)
|
if isinstance(v, map)
|
||||||
self.json_fdump_map(f, v)
|
self.json_fdump_map(f, v)
|
||||||
elif isinstance(v, list)v
|
elif isinstance(v, list)
|
||||||
self.json_fdump_list(f, v)
|
self.json_fdump_list(f, v)
|
||||||
else
|
else
|
||||||
f.write(json.dump(v))
|
f.write(json.dump(v))
|
||||||
|
|
Loading…
Reference in New Issue