Pretty-printing for Core/Go/Syntax.lean. Unlike every other Pretty.lean in this repo, this
one is not a debug dump — it is Network2Go's code generator: the .go file the compiler
ships is whatever this module prints. (Guarded2Network has no pretty-printer at all and dumps
via reprStr; that path stays for -d dump-network, and -d dump-go will reuse this one.)
keywordsandpredeclaredare two tables, not one: Go's reserved words are escaped by the printer, while its predeclared identifiers are not — escaping those would rewrite the generated code's own references toint/any/comparable/lenintoint__/comparable__.predeclaredis exported forNetwork2Goto rename user-chosen names against, since only the pass knows which names came from the specification; identifier hygiene is enforced per pass, not only by the printer.- Precedence levels are Go's own:
||1,&&2, comparisons 3,+/-4,*///%5, unary 6, selector/index/call 7.Common/Pretty.lean'sinfixl/prefixcombinators parenthesize against them, so no expression is over-parenthesized. - Blocks always break (
Std.Format.indentwithout a surroundinggroup): generated Go is read andgofmt-ed by whoever consumes it, so a stable one-statement-per-line layout is worth more than a compact one. - Expressions and statements print from one
mutualblock, sinceExpression.funcLitcarries a statement body. Statement cases therefore callExpression.pretty · 0directly rather than going through theStd.ToFormatinstance, which is only available once the block closes. - String literals print as Go raw strings (
`…`), so no escaping pass is needed. A source string containing a backtick would break this; TLA⁺'s own string syntax has no way to write one. printcompiles to Go's builtinprintln, notfmt.Println, so that generated code needs no import beyond the runtime library.
Go's 25 reserved words. These can never be identifiers, in any position, so the printer escapes them unconditionally.
Exported alongside predeclared so that Network2Go can rename a user-chosen name out of this
set rather than leaving it to sanitize below — a rename that knows the name's provenance can pick
a spelling that stays distinct from every other name, which a blind suffix cannot.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Go's predeclared identifiers — types, constants and builtin functions living in the universe
block. Unlike keywords these are ordinary identifiers that a declaration may legally shadow, so
the printer must not escape them: the generated code refers to int, any, comparable,
error and append/len/make by name constantly, and escaping them would turn those into
int__/comparable__.
A user-chosen name colliding with one of these still has to be renamed — shadowing int in a
file that also emits int for TLA⁺'s Int would silently change what the generated code means.
That rename belongs to Network2Go, which is the only place that knows whether a name came from
the specification or from the compiler; this set is exported for it to consult. Hygiene is
enforced per pass, not only by the printer.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Escape an identifier that would otherwise be a Go reserved word. Applied at every
identifier-print site — a backstop, not the whole hygiene story: see predeclared.
Unreachable for anything Network2Go emits, which renames user-chosen names out of keywords
itself; this catches only a name reaching the printer from somewhere that did not.
The suffix is a single _, because Network2Go spends underscore-run parity to separate
user-written names from compiler-introduced ones: a doubled suffix lands in the user half, so type
and a user's own type_ would both print type__. An odd-length suffix cannot collide with
either.
Equations
- Go.sanitize name = if name ∈ Go.keywords then name ++ "_" else name
Instances For
Equations
- Go.instToFormatTyp = { format := Go.Typ.pretty }
Equations
Instances For
Equations
- Go.BinaryOperator.add.symbol = "+"
- Go.BinaryOperator.sub.symbol = "-"
- Go.BinaryOperator.mul.symbol = "*"
- Go.BinaryOperator.div.symbol = "/"
- Go.BinaryOperator.mod.symbol = "%"
- Go.BinaryOperator.eq.symbol = "=="
- Go.BinaryOperator.ne.symbol = "!="
- Go.BinaryOperator.lt.symbol = "<"
- Go.BinaryOperator.le.symbol = "<="
- Go.BinaryOperator.gt.symbol = ">"
- Go.BinaryOperator.ge.symbol = ">="
- Go.BinaryOperator.and.symbol = "&&"
- Go.BinaryOperator.or.symbol = "||"
Instances For
Go's binary-operator precedence: *///% bind tighter than +/-, which bind tighter than
the comparisons, then &&, then ||.
Equations
- Go.BinaryOperator.mul.precedence = 5
- Go.BinaryOperator.div.precedence = 5
- Go.BinaryOperator.mod.precedence = 5
- Go.BinaryOperator.add.precedence = 4
- Go.BinaryOperator.sub.precedence = 4
- Go.BinaryOperator.eq.precedence = 3
- Go.BinaryOperator.ne.precedence = 3
- Go.BinaryOperator.lt.precedence = 3
- Go.BinaryOperator.le.precedence = 3
- Go.BinaryOperator.gt.precedence = 3
- Go.BinaryOperator.ge.precedence = 3
- Go.BinaryOperator.and.precedence = 2
- Go.BinaryOperator.or.precedence = 1
Instances For
Equations
- Go.Builtin.len.name = "len"
- Go.Builtin.cap.name = "cap"
- Go.Builtin.append.name = "append"
Instances For
Takes the expression formatter as an argument rather than resolving it from Std.ToFormat:
Ref is printed from inside the Expression/Statement mutual block below, where the instance
for Expression does not exist yet.
Equations
- Go.instToFormatRef = { format := Go.Ref.pretty Std.format }
Equations
- Go.instToFormatExpression = { format := fun (x : Go.Expression α) => x.pretty 0 }
Equations
- Go.instToFormatStatement = { format := Go.Statement.pretty }
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Go.instToFormatFunction = { format := Go.Function.pretty }
A top-level declaration. The var form spells its type even when there is an initializer, so
that a nil-valued or otherwise uninferable right-hand side still declares the right thing, and
because the compilation listings do.
Equations
- One or more equations did not get rendered due to their size.
- (Go.Declaration.function F).pretty = F.pretty
- (Go.Declaration.typ name τ).pretty = Std.format "type " ++ Std.format (Go.sanitize name) ++ Std.format " " ++ Std.format τ
Instances For
Equations
- Go.instToFormatDeclaration = { format := Go.Declaration.pretty }