Short-circuiting Boolean "and" and "or" operators.
This commit is contained in:
1 parent
c5ab3b2336
commit
6e6ea50763
5 files changed
+62
-5
No files matched your search
+40
-5
@@ -348,14 +348,49 @@ block gen_definedor(block a, block b) {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static block gen_condbranch(block iftrue, block iffalse) {
|
||||||
|
block b = gen_noop();
|
||||||
|
block_append(&iftrue, gen_op_target(JUMP, iffalse));
|
||||||
|
block_append(&b, gen_op_target(JUMP_F, iftrue));
|
||||||
|
block_append(&b, iftrue);
|
||||||
|
block_append(&b, iffalse);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
block gen_and(block a, block b) {
|
||||||
|
// a and b = if a then (if b then true else false) else false
|
||||||
|
block code = gen_op_simple(DUP);
|
||||||
|
block_append(&code, a);
|
||||||
|
|
||||||
|
block if_a_true = gen_op_simple(POP);
|
||||||
|
block_append(&if_a_true, b);
|
||||||
|
block_append(&if_a_true, gen_condbranch(gen_op_const(LOADK, jv_true()),
|
||||||
|
gen_op_const(LOADK, jv_false())));
|
||||||
|
block_append(&code, gen_condbranch(if_a_true,
|
||||||
|
block_join(gen_op_simple(POP), gen_op_const(LOADK, jv_false()))));
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
block gen_or(block a, block b) {
|
||||||
|
// a or b = if a then true else (if b then true else false)
|
||||||
|
block code = gen_op_simple(DUP);
|
||||||
|
block_append(&code, a);
|
||||||
|
|
||||||
|
block if_a_false = gen_op_simple(POP);
|
||||||
|
block_append(&if_a_false, b);
|
||||||
|
block_append(&if_a_false, gen_condbranch(gen_op_const(LOADK, jv_true()),
|
||||||
|
gen_op_const(LOADK, jv_false())));
|
||||||
|
block_append(&code, gen_condbranch(block_join(gen_op_simple(POP), gen_op_const(LOADK, jv_true())),
|
||||||
|
if_a_false));
|
||||||
|
return code;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
block gen_cond(block cond, block iftrue, block iffalse) {
|
block gen_cond(block cond, block iftrue, block iffalse) {
|
||||||
block b = gen_op_simple(DUP);
|
block b = gen_op_simple(DUP);
|
||||||
block_append(&b, cond);
|
block_append(&b, cond);
|
||||||
|
block_append(&b, gen_condbranch(block_join(gen_op_simple(POP), iftrue),
|
||||||
block_append(&iftrue, gen_op_target(JUMP, iffalse));
|
block_join(gen_op_simple(POP), iffalse)));
|
||||||
block_append(&b, gen_op_target(JUMP_F, iftrue));
|
|
||||||
block_append(&b, block_join(gen_op_simple(POP), iftrue));
|
|
||||||
block_append(&b, block_join(gen_op_simple(POP), iffalse));
|
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ block gen_both(block a, block b);
|
|||||||
block gen_collect(block expr);
|
block gen_collect(block expr);
|
||||||
block gen_assign(block expr);
|
block gen_assign(block expr);
|
||||||
block gen_definedor(block a, block b);
|
block gen_definedor(block a, block b);
|
||||||
|
block gen_and(block a, block b);
|
||||||
|
block gen_or(block a, block b);
|
||||||
|
|
||||||
block gen_cond(block cond, block iftrue, block iffalse);
|
block gen_cond(block cond, block iftrue, block iffalse);
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
"then" { return THEN; }
|
"then" { return THEN; }
|
||||||
"else" { return ELSE; }
|
"else" { return ELSE; }
|
||||||
"elif" { return ELSE_IF; }
|
"elif" { return ELSE_IF; }
|
||||||
|
"and" { return AND; }
|
||||||
|
"or" { return OR; }
|
||||||
"end" { return END; }
|
"end" { return END; }
|
||||||
"//" { return DEFINEDOR; }
|
"//" { return DEFINEDOR; }
|
||||||
"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"\$" { return yytext[0];}
|
"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"\$" { return yytext[0];}
|
||||||
|
|||||||
+12
@@ -34,9 +34,13 @@
|
|||||||
%token ELSE "else"
|
%token ELSE "else"
|
||||||
%token ELSE_IF "elif"
|
%token ELSE_IF "elif"
|
||||||
%token END "end"
|
%token END "end"
|
||||||
|
%token AND "and"
|
||||||
|
%token OR "or"
|
||||||
%right "//"
|
%right "//"
|
||||||
%nonassoc '=' SETPIPE
|
%nonassoc '=' SETPIPE
|
||||||
%nonassoc EQ
|
%nonassoc EQ
|
||||||
|
%left OR
|
||||||
|
%left AND
|
||||||
%left '+'
|
%left '+'
|
||||||
|
|
||||||
|
|
||||||
@@ -99,6 +103,14 @@ Exp '=' Exp {
|
|||||||
$$ = gen_assign(assign);
|
$$ = gen_assign(assign);
|
||||||
} |
|
} |
|
||||||
|
|
||||||
|
Exp "or" Exp {
|
||||||
|
$$ = gen_or($1, $3);
|
||||||
|
} |
|
||||||
|
|
||||||
|
Exp "and" Exp {
|
||||||
|
$$ = gen_and($1, $3);
|
||||||
|
} |
|
||||||
|
|
||||||
Exp "//" Exp {
|
Exp "//" Exp {
|
||||||
$$ = gen_definedor($1, $3);
|
$$ = gen_definedor($1, $3);
|
||||||
} |
|
} |
|
||||||
|
|||||||
@@ -254,3 +254,9 @@ def inc(x): x |= .+1; inc(.[].a)
|
|||||||
[{"foo":[1,2], "bar": 42}, {"foo":[1], "bar": null}, {"foo":[null,false,3], "bar": 18}, {"foo":[], "bar":42}, {"foo": [null,false,null], "bar": 41}]
|
[{"foo":[1,2], "bar": 42}, {"foo":[1], "bar": null}, {"foo":[null,false,3], "bar": 18}, {"foo":[], "bar":42}, {"foo": [null,false,null], "bar": 41}]
|
||||||
[[1,2], [1], [3], [42], [41]]
|
[[1,2], [1], [3], [42], [41]]
|
||||||
|
|
||||||
|
.[] | [.[0] and .[1], .[0] or .[1]]
|
||||||
|
[[true,[]], [false,1], [42,null], [null,false]]
|
||||||
|
[true,true]
|
||||||
|
[false,true]
|
||||||
|
[false,true]
|
||||||
|
[false,false]
|
||||||
Reference in new issue
Block a user