diff --git a/compiler/gengo/gen_cmd.go b/compiler/gengo/gen_cmd.go index 82e5f27..bc893a1 100644 --- a/compiler/gengo/gen_cmd.go +++ b/compiler/gengo/gen_cmd.go @@ -46,18 +46,23 @@ func (g *Generator) emitGoCmd(s *ast.GoCmd) { g.writeln("{") g.indent++ g.writeln("wa := t.WA.(*hbrdd.WorkAreaManager)") - g.writeln("if area := wa.Current(); area != nil {") + g.writeln("if _area := wa.Current(); _area != nil {") g.indent++ switch s.Direction { case "TOP": - g.writeln("area.GoTop()") + g.writeln("_area.GoTop()") case "BOTTOM": - g.writeln("area.GoBottom()") + g.writeln("_area.GoBottom()") default: if s.RecNo != nil { - g.emitExpr(s.RecNo) - g.writeln("area.GoTo(uint32(t.Pop2().AsNumInt()))") + // Optimize: literal integers skip stack ops + if lit, ok := s.RecNo.(*ast.LiteralExpr); ok && lit.Kind == token.INT { + g.writeln(fmt.Sprintf("_area.GoTo(uint32(%s))", lit.Value)) + } else { + g.emitExpr(s.RecNo) + g.writeln("_area.GoTo(uint32(t.Pop2().AsNumInt()))") + } } } @@ -71,14 +76,26 @@ func (g *Generator) emitSkipCmd(s *ast.SkipCmd, locals localMap) { g.writeln("{") g.indent++ g.writeln("wa := t.WA.(*hbrdd.WorkAreaManager)") - g.writeln("if area := wa.Current(); area != nil {") + g.writeln("if _area := wa.Current(); _area != nil {") g.indent++ if s.Count != nil { - g.emitExpr(s.Count) - g.writeln("area.Skip(t.Pop2().AsNumInt())") + // Optimize: literal skip count avoids stack ops + if lit, ok := s.Count.(*ast.LiteralExpr); ok && lit.Kind == token.INT { + g.writeln(fmt.Sprintf("_area.Skip(%s)", lit.Value)) + } else if unary, ok := s.Count.(*ast.UnaryExpr); ok { + if lit2, ok2 := unary.X.(*ast.LiteralExpr); ok2 && lit2.Kind == token.INT { + g.writeln(fmt.Sprintf("_area.Skip(-%s)", lit2.Value)) + } else { + g.emitExpr(s.Count) + g.writeln("_area.Skip(t.Pop2().AsNumInt())") + } + } else { + g.emitExpr(s.Count) + g.writeln("_area.Skip(t.Pop2().AsNumInt())") + } } else { - g.writeln("area.Skip(1)") + g.writeln("_area.Skip(1)") } g.indent-- @@ -118,27 +135,27 @@ func (g *Generator) emitReplaceCmd(s *ast.ReplaceCmd, locals localMap) { g.writeln("{") g.indent++ g.writeln("wa := t.WA.(*hbrdd.WorkAreaManager)") - g.writeln("if area := wa.Current(); area != nil {") + g.writeln("if _area := wa.Current(); _area != nil {") + g.indent++ + + // Cache type assertion once (avoids N assertions for N fields) + g.writeln("_dbf, _ := _area.(*dbf.DBFArea)") + g.writeln("if _dbf != nil {") g.indent++ for _, rf := range s.Fields { - // Get field name if ident, ok := rf.Field.(*ast.IdentExpr); ok { - g.writeln(fmt.Sprintf("if _fi := area.(*dbf.DBFArea).FieldIndex(%q); _fi >= 0 {", ident.Name)) - g.indent++ g.emitExpr(rf.Value) - g.writeln(fmt.Sprintf("area.PutValue(_fi, t.Pop2())")) - g.indent-- - g.writeln("}") + g.writeln(fmt.Sprintf("_dbf.PutValue(_dbf.FieldIndex(%q), t.Pop2())", ident.Name)) } } - // No Flush here — Harbour defers write until DBCOMMIT/CLOSE/GoTo. - // PutValue sets dirty flag; flushRecord writes on next GoTo or Close. g.indent-- g.writeln("}") g.indent-- g.writeln("}") + g.indent-- + g.writeln("}") } // --- @ SAY / GET / READ commands ---