diff --git a/compiler/gengo/gengo.go b/compiler/gengo/gengo.go index be36dfe..311e60f 100644 --- a/compiler/gengo/gengo.go +++ b/compiler/gengo/gengo.go @@ -2077,8 +2077,17 @@ func hasLoopStmt(s ast.Stmt) bool { func (g *Generator) emitSwitch(s *ast.SwitchStmt, locals localMap) { + // Wrap the whole thing in a one-iteration `for` so: + // 1. `_sw` stays scoped to the switch. + // 2. `EXIT` inside a CASE emits `break` and targets this loop, + // matching Harbour SWITCH semantics (EXIT terminates SWITCH). + // 3. Empty SWITCH (`SWITCH x ENDSWITCH`, common in conditional- + // compile test files) stays valid Go. + g.writeln("for {") + g.indent++ g.emitExpr(s.Expr) g.writeln("_sw := t.Pop2()") + g.writeln("_ = _sw") // silence unused-var warning when no cases reference it first := true for _, c := range s.Cases { if first { @@ -2096,13 +2105,28 @@ func (g *Generator) emitSwitch(s *ast.SwitchStmt, locals localMap) { g.indent-- } if len(s.Otherwise) > 0 { - g.writeln("} else {") - g.indent++ - for _, stmt := range s.Otherwise { - g.emitStmt(stmt, locals) + if first { + // No CASE arms — emit the OTHERWISE body as-is, no if/else. + for _, stmt := range s.Otherwise { + g.emitStmt(stmt, locals) + } + } else { + g.writeln("} else {") + g.indent++ + for _, stmt := range s.Otherwise { + g.emitStmt(stmt, locals) + } + g.indent-- + g.writeln("}") } - g.indent-- + } else if !first { + // Had CASE arms, no OTHERWISE — close the if/else-if chain. + g.writeln("}") } + // Always break out of our one-iteration `for` wrapper, regardless + // of which (or no) case ran. + g.writeln("break") + g.indent-- g.writeln("}") }