perf(gengo): short-circuit AND/OR with literal LHS

Skip the PushBool/PopLogical/branch wrapper when the LHS of .AND. /
.OR. is a bare .T./.F. literal. `.T. .AND. X` emits X alone;
`.F. .AND. X` emits PushBool(false) with X dropped; symmetric for
OR. Common after constant-folding a sub-expression — pairs with
the earlier dead-IF-branch peephole.

FiveSql2 43/43, Harbour compat 56/56. Verified via /tmp/test_andor.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-18 08:35:22 +09:00
parent 3f8ef7daef
commit 1b6d913905

View File

@@ -1938,8 +1938,19 @@ func (g *Generator) emitExpr(expr ast.Expr) {
g.emitLiteral(folded)
break
}
// Short-circuit AND/OR: Harbour evaluates right operand only if needed
// Short-circuit AND/OR: Harbour evaluates right operand only if needed.
// With a literal LHS we can skip the PushBool/PopLogical roundtrip
// entirely — .T. .AND. B folds to B, .F. .AND. B folds to false,
// and symmetrically for OR.
if e.Op == token.AND {
if v, ok := boolLiteralValue(e.Left); ok {
if v {
g.emitExpr(e.Right)
} else {
g.writeln("t.PushBool(false)")
}
break
}
g.emitExpr(e.Left)
g.writeln("if !t.PopLogical() {")
g.writeln("t.PushBool(false)")
@@ -1947,6 +1958,14 @@ func (g *Generator) emitExpr(expr ast.Expr) {
g.emitExpr(e.Right)
g.writeln("}")
} else if e.Op == token.OR {
if v, ok := boolLiteralValue(e.Left); ok {
if v {
g.writeln("t.PushBool(true)")
} else {
g.emitExpr(e.Right)
}
break
}
g.emitExpr(e.Left)
g.writeln("if t.PopLogical() {")
g.writeln("t.PushBool(true)")