From 1b6d9139053fc9cedc6ac27f7ddb9f292f2b903c Mon Sep 17 00:00:00 2001 From: CharlesKWON Date: Sat, 18 Apr 2026 08:35:22 +0900 Subject: [PATCH] perf(gengo): short-circuit AND/OR with literal LHS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- compiler/gengo/gengo.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/compiler/gengo/gengo.go b/compiler/gengo/gengo.go index d66b800..c4501d1 100644 --- a/compiler/gengo/gengo.go +++ b/compiler/gengo/gengo.go @@ -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)")