Let an unbroken "while true" terminate a block
diff --git a/lang/ast/ast.go b/lang/ast/ast.go
index 363c9a7..78a7819 100644
--- a/lang/ast/ast.go
+++ b/lang/ast/ast.go
@@ -593,6 +593,11 @@
 func (n *While) SetHasBreak()         { n.flags |= FlagsHasBreak }
 func (n *While) SetHasContinue()      { n.flags |= FlagsHasContinue }
 
+func (n *While) IsWhileTrue() bool {
+	condition := n.mhs.AsExpr()
+	return (condition.Operator() == 0) && (condition.Ident() == t.IDTrue)
+}
+
 func NewWhile(label t.ID, condition *Expr, asserts []*Node) *While {
 	return &While{
 		kind:  KWhile,
@@ -1013,10 +1018,9 @@
 
 // Terminates returns whether a block of statements terminates. In other words,
 // whether the block is non-empty and its final statement is a "return",
-// "break", "continue" or an "if-else" chain where all branches terminate.
+// "break", "continue", a "while true" that doesn't break or an "if-else" chain
+// where all branches terminate.
 func Terminates(body []*Node) bool {
-	// TODO: strengthen this to include "while" statements? For inspiration,
-	// the Go spec has https://golang.org/ref/spec#Terminating_statements
 	if len(body) == 0 {
 		return false
 	}
@@ -1041,6 +1045,9 @@
 		return true
 	case KRet:
 		return n.AsRet().Keyword() == t.IDReturn
+	case KWhile:
+		n := n.AsWhile()
+		return n.IsWhileTrue() && !n.HasBreak()
 	}
 	return false
 }
diff --git a/lang/parse/parse.go b/lang/parse/parse.go
index ad1a227..994dd22 100644
--- a/lang/parse/parse.go
+++ b/lang/parse/parse.go
@@ -790,17 +790,17 @@
 		if err != nil {
 			return nil, err
 		}
-		doubleCurly := p.peek1() == t.IDOpenDoubleCurly
-		if doubleCurly && ((condition.Operator() != 0) || (condition.Ident() != t.IDTrue)) {
-			return nil, fmt.Errorf(`parse: double {{ }} while loop condition isn't "true" at %s:%d`,
-				p.filename, p.line())
-		}
 
 		n := a.NewWhile(label, condition, asserts)
 		if !p.loops.Push(n) {
 			return nil, fmt.Errorf(`parse: duplicate loop label %s at %s:%d`,
 				label.Str(p.tm), p.filename, p.line())
 		}
+		doubleCurly := p.peek1() == t.IDOpenDoubleCurly
+		if doubleCurly && !n.IsWhileTrue() {
+			return nil, fmt.Errorf(`parse: double {{ }} while loop condition isn't "true" at %s:%d`,
+				p.filename, p.line())
+		}
 		body, err := p.parseBlock(doubleCurly)
 		if err != nil {
 			return nil, err