From c69c9f50075e01fc9cb13998ad938e44a5f7e84c Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Sat, 16 Nov 2024 16:24:10 +0100 Subject: [PATCH 01/47] First version of reformatter --- .../silver/ast/pretty/PrettyPrinter.scala | 12 + .../ast/utility/rewriter/Rewritable.scala | 2 +- .../viper/silver/frontend/Frontend.scala | 6 +- .../viper/silver/parser/FastParser.scala | 31 +- .../viper/silver/parser/MacroExpander.scala | 4 +- .../scala/viper/silver/parser/ParseAst.scala | 472 +++++++++++++++--- .../viper/silver/parser/ParseAstKeyword.scala | 54 +- .../silver/parser/ReformatPrettyPrinter.scala | 172 +++++++ .../silver/plugin/ParserPluginTemplate.scala | 8 +- .../standard/adt/AdtPASTExtension.scala | 27 + .../PredicateInstancePASTExtension.scala | 4 + .../standard/refute/RefutePASTExtension.scala | 3 + .../smoke/UnreachablePASTExtension.scala | 3 + .../TerminationPASTExtension.scala | 11 +- .../termination/TerminationPlugin.scala | 2 +- src/test/scala/ASTTransformationTests.scala | 10 +- src/test/scala/PluginTests.scala | 2 +- src/test/scala/SemanticAnalysisTests.scala | 4 +- 18 files changed, 742 insertions(+), 85 deletions(-) create mode 100644 src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala diff --git a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala index 64e1db3f4..92c88c12e 100644 --- a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala +++ b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala @@ -376,6 +376,18 @@ trait FastPrettyPrinterBase extends PrettyPrintPrimitives { def <@> (dr: Cont) : Cont = if (dl == nil) dr else if (dr == nil) dl else dl <> line <> dr + + def <@@> (dr: Cont) : Cont = + if (dl == nil) dr else if (dr == nil) dl else dl <> linebreak <> dr + + def <@@@> (dr: Cont) : Cont = + if (dl == nil) dr else if (dr == nil) dl else dl <> dr + + def <@+> (dr: Cont) : Cont = + if (dl == nil) dr else if (dr == nil) dl else dl <> dr + + def <+@> (dr: Cont) : Cont = + if (dl == nil) dr else if (dr == nil) dl else dl <> space <> dr } def line: Cont = line(" ") diff --git a/src/main/scala/viper/silver/ast/utility/rewriter/Rewritable.scala b/src/main/scala/viper/silver/ast/utility/rewriter/Rewritable.scala index 434c2ccf4..e9c9adec9 100644 --- a/src/main/scala/viper/silver/ast/utility/rewriter/Rewritable.scala +++ b/src/main/scala/viper/silver/ast/utility/rewriter/Rewritable.scala @@ -6,7 +6,7 @@ package viper.silver.ast.utility.rewriter -import viper.silver.parser.PNode +import viper.silver.parser.{PDomainMembers, PNode} import viper.silver.ast.{AtomicType, BackendFuncApp, DomainFuncApp, ErrorTrafo, FuncApp, Info, Node, Position} import scala.reflect.runtime.{universe => reflection} diff --git a/src/main/scala/viper/silver/frontend/Frontend.scala b/src/main/scala/viper/silver/frontend/Frontend.scala index bb104d4c1..0159cc61b 100644 --- a/src/main/scala/viper/silver/frontend/Frontend.scala +++ b/src/main/scala/viper/silver/frontend/Frontend.scala @@ -7,12 +7,11 @@ package viper.silver.frontend import java.nio.file.Path - import org.slf4j.LoggerFactory import ch.qos.logback.classic.Logger - import viper.silver.ast._ import viper.silver.ast.utility.{DiskLoader, FileLoader} +import viper.silver.parser.PProgram import viper.silver.reporter.StdIOReporter import viper.silver.verifier._ import viper.silver.reporter.Reporter @@ -189,6 +188,9 @@ trait DefaultFrontend extends Frontend with DefaultPhases with SingleFileFronten throw new NoSuchElementException(msg) } + // TODO: How to do this properly? + def parseResult: PProgram = pProgram.get.asInstanceOf[PProgram] + def state = _state def errors = _errors def pProgram = _parsingResult diff --git a/src/main/scala/viper/silver/parser/FastParser.scala b/src/main/scala/viper/silver/parser/FastParser.scala index eae845045..a9cd7ab69 100644 --- a/src/main/scala/viper/silver/parser/FastParser.scala +++ b/src/main/scala/viper/silver/parser/FastParser.scala @@ -104,6 +104,25 @@ object FastParserCompanion { ).pos } + def space[$: P]: P[PSpace] = P(("\t" | " ") map {_ => PSpace() }) + + def newline[$: P]: P[PNewLine] = P((StringIn("\n\r") | "\n" | "\r") map {_ => PNewLine() }) + + def lineComment[$: P]: P[PComment] = { + P(("//" ~~ CharsWhile(_ != '\n').?.! ~~ ("\n" | End)).map { content => + PComment(content, false) + }) + } + + def blockComment[$: P]: P[PComment] = P(("/*" ~~ (!StringIn("*/") ~~ AnyChar).repX.! ~~ "*/").map { content => + PComment(content, true) + }) + + def comment[$: P]: P[PComment] = lineComment | blockComment + + def programTrivia[$: P]: P[Seq[Trivia]] = { + P((space | newline | comment | (AnyChar.map(_ => POther()))).repX) + } /** * A parser which matches leading whitespaces. See `LeadingWhitespace.lw` for more info. Can only be operated on in * restricted ways (e.g. `?`, `rep`, `|` or `map`), requiring that it is eventually appended to a normal parser (of type `P[V]`). @@ -859,7 +878,7 @@ class FastParser { P(programMember.rep map (members => { val warnings = _warnings _warnings = Seq() - PProgram(Nil, members)(_, warnings) + PProgram(Nil, members)(_, warnings, Nil, "") })).pos def preambleImport[$: P]: P[PKw.Import => PAnnotationsPosition => PImport] = P( @@ -886,7 +905,7 @@ class FastParser { val axioms1 = members collect { case m: PAxiom1 => m } val funcs = funcs1 map (f => (PDomainFunction(f.annotations, f.unique, f.function, f.idndef, f.args, f.c, f.typ, f.interpretation)(f.pos), f.s)) val axioms = axioms1 map (a => (PAxiom(a.annotations, a.axiom, a.idndef, a.exp)(a.pos), a.s)) - val allMembers = block.update(PDomainMembers(PDelimited(funcs)(NoPosition, NoPosition), PDelimited(axioms)(NoPosition, NoPosition))(block.pos)) + val allMembers = block.update(PDomainMembers(PDelimited(funcs)(NoPosition, NoPosition), PDelimited(axioms)(NoPosition, NoPosition))(block.pos, block.inner)) k => ap: PAnnotationsPosition => PDomain( ap.annotations, k, @@ -970,7 +989,11 @@ class FastParser { // Assume entire file is correct and try parsing it quickly fastparse.parse(s, entireProgram(_)) match { - case Parsed.Success(value, _) => return value + case Parsed.Success(value, _) => { + value.offsets = _line_offset; + value.rawProgram = s; + return value; + } case _: Parsed.Failure => } // There was a parsing error, parse member by member to get all errors @@ -1018,7 +1041,7 @@ class FastParser { val warnings = _warnings _warnings = Nil val pos = (FilePosition(lineCol.getPos(0)), FilePosition(lineCol.getPos(res.get.index))) - PProgram(Nil, members)(pos, errors ++ warnings) + PProgram(Nil, members)(pos, errors ++ warnings, Nil, ""); } object ParserExtension extends ParserPluginTemplate { diff --git a/src/main/scala/viper/silver/parser/MacroExpander.scala b/src/main/scala/viper/silver/parser/MacroExpander.scala index 0a5bcfee9..6419a934d 100644 --- a/src/main/scala/viper/silver/parser/MacroExpander.scala +++ b/src/main/scala/viper/silver/parser/MacroExpander.scala @@ -156,9 +156,9 @@ object MacroExpander { pos._1 } } - return PProgram(newImported, program.members)(program.pos, program.localErrors ++ reports :+ ParseError(msg, location)) + return PProgram(newImported, program.members)(program.pos, program.localErrors ++ reports :+ ParseError(msg, location), program.offsets, program.rawProgram) } - PProgram(newImported, newMembers)(program.pos, program.localErrors ++ reports) + PProgram(newImported, newMembers)(program.pos, program.localErrors ++ reports, program.offsets, program.rawProgram) } doExpandDefinesAll(p, reports) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index cc4fd40d5..3b3345ae6 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -6,10 +6,16 @@ package viper.silver.parser + +import viper.silver.ast +import viper.silver.ast.{FilePosition, HasLineColumn, Position} +import viper.silver.parser.ReformatPrettyPrinter.{formatTrivia, show, showAnnotations, showAny, showBody, showInvs, showOption, showPresPosts, showReturns, showSeq} + import java.util.concurrent.atomic.{AtomicInteger, AtomicLong} import viper.silver.ast.utility.Visitor -import viper.silver.ast.utility.rewriter.{Rewritable, StrategyBuilder, HasExtraVars, HasExtraValList} -import viper.silver.ast.{Exp, FilePosition, HasLineColumn, Member, NoPosition, Position, SourcePosition, Stmt, Type} +import viper.silver.ast.utility.rewriter.{HasExtraValList, HasExtraVars, Rewritable, StrategyBuilder} +import viper.silver.ast.{Exp, Member, NoPosition, SourcePosition, Stmt, Type} +import viper.silver.parser.PSymOp.{Iff, Implies} import viper.silver.parser.TypeHelper._ import viper.silver.verifier.ParseReport @@ -30,7 +36,7 @@ trait Where { * The root of the parser abstract syntax tree. Note that we prefix all nodes with `P` to avoid confusion * with the actual Viper abstract syntax tree. */ -trait PNode extends Where with Product with Rewritable with HasExtraValList { +trait PNode extends Where with Product with Rewritable with HasExtraValList with Reformattable { /* Should output something that can be displayed to the user. */ def pretty: String @@ -231,7 +237,9 @@ trait PIdentifier extends PLeaf { override def display = name } -case class PIdnDef(name: String)(val pos: (Position, Position)) extends PNode with PIdentifier +case class PIdnDef(name: String)(val pos: (Position, Position)) extends PNode with PIdentifier { + override def reformat(ctx: ReformatterContext): Cont = text(name) +} trait PIdnUse extends PNode with PIdentifier { def decl: Option[PDeclarationInner] @@ -280,6 +288,8 @@ case class PIdnUseExp(name: String)(val pos: (Position, Position)) extends PIdnU } override def rename(newName: String) = PIdnUseExp(newName)(pos) + + override def reformatExp(ctx: ReformatterContext): Cont = text(name) } case class PIdnRef[T <: PDeclarationInner](name: String)(val pos: (Position, Position))(implicit val ctag: scala.reflect.ClassTag[T]) extends PIdnUseName[T] { override def rename(newName: String): PIdnUse = PIdnRef(newName)(pos) @@ -294,6 +304,8 @@ case class PIdnRef[T <: PDeclarationInner](name: String)(val pos: (Position, Pos case _ => None } override def getExtraVals: Seq[Any] = Seq(pos, ctag) + + override def reformat(ctx: ReformatterContext): Cont = name } case class PVersionedIdnUseExp(name: String, version: String, separator: String = "@")(val pos: (Position, Position)) extends PIdnUseName[PTypedVarDecl] with PExp { @@ -310,6 +322,8 @@ case class PVersionedIdnUseExp(name: String, version: String, separator: String typ = typ.substitute(ts) assert(typ.isGround) } + + override def reformatExp(ctx: ReformatterContext): Cont = text(versionedName) } /////////////////////////////////////////////////////////////////////////// @@ -318,7 +332,9 @@ case class PVersionedIdnUseExp(name: String, version: String, separator: String trait PAnyFormalArgDecl extends PNode with PUnnamedTypedDeclaration with PPrettySubnodes /** The declaration of an argument to a domain function. Not a `PDeclaration` as it will never clash. */ -case class PDomainFunctionArg(name: Option[PIdnDef], c: Option[PSym.Colon], typ: PType)(val pos: (Position, Position)) extends PAnyFormalArgDecl +case class PDomainFunctionArg(name: Option[PIdnDef], c: Option[PSym.Colon], typ: PType)(val pos: (Position, Position)) extends PAnyFormalArgDecl { + override def reformat(ctx: ReformatterContext): Cont = showOption(name, ctx) <> showOption(c, ctx) <+@> show(typ, ctx) +} object PDomainFunctionArg { def apply(d: PIdnTypeBinding): PDomainFunctionArg = PDomainFunctionArg(Some(d.idndef), Some(d.c), d.typ)(d.pos) } @@ -340,22 +356,30 @@ sealed trait PTypedVarDecl extends PTypedDeclaration with PDeclarationInner with sealed trait PAssignableVarDecl extends PTypedVarDecl /** Any argument to a method, function or predicate. */ -case class PFormalArgDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAnyFormalArgDecl with PTypedVarDecl with PMemberDeclaration with PMemberUniqueDeclaration +case class PFormalArgDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAnyFormalArgDecl with PTypedVarDecl with PMemberDeclaration with PMemberUniqueDeclaration { + override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <> show(c, ctx) <+> show(typ, ctx) +} object PFormalArgDecl { def apply(d: PIdnTypeBinding): PFormalArgDecl = PFormalArgDecl(d.idndef, d.c, d.typ)(d.pos) } /** The return arguments of methods. */ -case class PFormalReturnDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAssignableVarDecl with PMemberDeclaration with PMemberUniqueDeclaration +case class PFormalReturnDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAssignableVarDecl with PMemberDeclaration with PMemberUniqueDeclaration { + override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <> show(c, ctx) <+> show(typ, ctx) +} object PFormalReturnDecl { def apply(d: PIdnTypeBinding): PFormalReturnDecl = PFormalReturnDecl(d.idndef, d.c, d.typ)(d.pos) } -case class PLogicalVarDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PTypedVarDecl with PLocalDeclaration with PScopeUniqueDeclaration +case class PLogicalVarDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PTypedVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { + override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <> show(c, ctx) <+> show(typ, ctx) +} object PLogicalVarDecl { def apply(d: PIdnTypeBinding): PLogicalVarDecl = PLogicalVarDecl(d.idndef, d.c, d.typ)(d.pos) } /** Declaration of a local variable. */ -case class PLocalVarDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAssignableVarDecl with PLocalDeclaration with PScopeUniqueDeclaration +case class PLocalVarDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAssignableVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { + override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <> show(c, ctx) <+> show(typ, ctx) +} object PLocalVarDecl { def apply(d: PIdnTypeBinding): PLocalVarDecl = PLocalVarDecl(d.idndef, d.c, d.typ)(d.pos) } @@ -363,6 +387,8 @@ case class PFieldDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Posi var decl: Option[PFields] = None override def annotations = decl.toSeq.flatMap(_.annotations) override def pretty = s"${idndef.pretty}: ${typ.pretty}" + + override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <> show(c, ctx) <+> show(typ, ctx) } object PFieldDecl { def apply(d: PIdnTypeBinding): PFieldDecl = PFieldDecl(d.idndef, d.c, d.typ)(d.pos) @@ -403,6 +429,8 @@ case class PPrimitiv[T <: PKeywordType](name: PReserved[T])(val pos: (Position, } override def pretty = name.pretty + + override def reformat(ctx: ReformatterContext): Cont = show(name, ctx) } case class PDomainType(domain: PIdnRef[PTypeDeclaration], args: Option[PDelimited.Comma[PSym.Bracket, PType]])(val pos: (Position, Position)) extends PGenericType with HasExtraVars { @@ -525,6 +553,8 @@ trait PGenericType extends PType { val argsPretty = if (typeArguments.isEmpty) "" else typeArguments.map(_.pretty).mkString("[", ", ", "]") s"$genericName$argsPretty" } + + override def reformat(ctx: ReformatterContext): Cont = text(pretty) } sealed trait PGenericCollectionType extends PGenericType { @@ -575,18 +605,20 @@ case class PMapType(map: PKw.Map, typ: PGrouped[PSym.Bracket, PPairArgument[PTyp * a real type by macro expansion. */ case class PMacroType(use: PCall) extends PType { - override val pos: (Position, Position) = use.pos + override val pos: (ast.Position, ast.Position) = use.pos override def pretty = use.pretty override def isValidOrUndeclared: Boolean = ??? override def substitute(ts: PTypeSubstitution): PType = ??? override def subNodes: Seq[PType] = ??? + + override def reformat(ctx: ReformatterContext): Cont = show(use, ctx) } /** Type used for internal nodes (e.g. typing predicate accesses) - should not be * the type of any expression whose value is meaningful in the translation. */ sealed trait PInternalType extends PType { - override val pos: (Position, Position) = (NoPosition, NoPosition) + override val pos: (ast.Position, ast.Position) = (NoPosition, NoPosition) override val subNodes: Seq[PType] = Seq() override def substitute(ts: PTypeSubstitution) = this } @@ -595,24 +627,28 @@ sealed trait PInternalType extends PType { case class PUnknown() extends PInternalType { override def isValidOrUndeclared = false override def pretty = "" + override def reformat(ctx: ReformatterContext): Cont = pretty } case class PBoolImpureType() extends PInternalType { override def isValidOrUndeclared = true override def isPure: Boolean = false override def pretty = "" + override def reformat(ctx: ReformatterContext): Cont = pretty } case class PBoolWandType() extends PInternalType { override def isValidOrUndeclared = true override def isPure: Boolean = false override def umbrella: Option[PType] = Some(TypeHelper.Impure) override def pretty = "" + override def reformat(ctx: ReformatterContext): Cont = pretty } case class PBoolPredicateType() extends PInternalType { override def isValidOrUndeclared = true override def isPure: Boolean = false override def umbrella: Option[PType] = Some(TypeHelper.Impure) override def pretty = "" + override def reformat(ctx: ReformatterContext): Cont = pretty } /** The type of a `PIdnUse` which refers to a function. Ensures that we get a @@ -627,13 +663,21 @@ case class PFunctionType(argTypes: Seq[PType], resultType: PType) extends PInter val argsPretty = argTypes.map(_.pretty).mkString("(", ", ", ")") s"$argsPretty: ${resultType.pretty}" } + + override def reformat(ctx: ReformatterContext): Cont = { + (if (argTypes.isEmpty) + text("()") + else + text("(") <> argTypes.map(show(_, ctx)).reduce(_ <> ", " <> _) <> text(")")) <> + text(": ") <> show(resultType, ctx) + } } /////////////////////////////////////////////////////////////////////////////////////// // Expressions // typeSubstitutions are the possible substitutions used for type checking and inference // The argument types are unified with the (fresh versions of) types are -trait PExp extends PNode with PPrettySubnodes { +trait PExp extends PNode with PPrettySubnodes with ReformattableExpression { var brackets: Option[PGrouped.Paren[PExp]] = None var typ: PType = PUnknown() @@ -654,11 +698,30 @@ trait PExp extends PNode with PPrettySubnodes { case Some(b) => s"${b.l.pretty}${super.pretty}${b.r.pretty}" case None => super.pretty } + + // Note: We override the `reformat` for all expressions here, classes implementing this trait + // should not override it. Instead, they should implement the `reformatExp` method. + override def reformat(ctx: ReformatterContext): Cont = { + // Unfortunately, we cannot just show exp.brackets, because then we end up in an + // endless recursion. So instead, we need to add them manually. + brackets match { + case Some(b) => { + if (b.l.isInstanceOf[PSym.Brace]) { + nest(defaultIndent, group(show(b.l, ctx) <@> this.reformatExp(ctx) <@> show(b.r, ctx))) + } else { + show(b.l, ctx) <> this.reformatExp(ctx) <> show(b.r, ctx) + } + } + case None => this.reformatExp(ctx) + } + } } case class PAnnotatedExp(annotation: PAnnotation, e: PExp)(val pos: (Position, Position)) extends PExp { override def typeSubstitutions: collection.Seq[PTypeSubstitution] = e.typeSubstitutions override def forceSubstitution(ts: PTypeSubstitution): Unit = e.forceSubstitution(ts) + + override def reformatExp(ctx: ReformatterContext): Cont = show(annotation, ctx) <@@> show(e, ctx) } trait PSubstitutionMap[S <: PSubstitutionMap[S]] { @@ -967,6 +1030,9 @@ case class PCall(idnref: PIdnRef[PCallable], callArgs: PDelimited.Comma[PSym.Par assert(typ.isGround) args.foreach(_.forceSubstitution(ts)) } + + override def reformatExp(ctx: ReformatterContext): Cont = show(idnref, ctx) <> + show(callArgs, ctx) <> typeAnnotated.map(e => show(e._1, ctx) <+> show(e._2, ctx)).getOrElse(nil) } class PBinExp(val left: PExp, val op: PReserved[PBinaryOp], val right: PExp)(val pos: (Position, Position)) extends POpApp { @@ -996,6 +1062,15 @@ class PBinExp(val left: PExp, val op: PReserved[PBinaryOp], val right: PExp)(val override def hashCode(): Int = viper.silver.utility.Common.generateHashCode(left, op.rs.operator, right) override def toString(): String = s"PBinExp($left,$op,$right)" + + override def reformatExp(ctx: ReformatterContext): Cont = { + op.rs match { + case Iff | Implies => + group(show(left, ctx) <+> show(op, ctx) <> nest(defaultIndent, line <> show(right, ctx))) + case _ => group(show(left, ctx) <@> show(op, ctx) <+> show(right, ctx)) + } + + } } object PBinExp { @@ -1010,6 +1085,8 @@ case class PMagicWandExp(override val left: PExp, wand: PSymOp.Wand, override va case class PUnExp(op: PReserved[PUnaryOp], exp: PExp)(val pos: (Position, Position)) extends POpApp { override val args = Seq(exp) override val signatures = op.rs.signatures + + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(exp, ctx) } case class PCondExp(cond: PExp, q: PSymOp.Question, thn: PExp, c: PSymOp.Colon, els: PExp)(val pos: (Position, Position)) extends POpApp { @@ -1017,6 +1094,10 @@ case class PCondExp(cond: PExp, q: PSymOp.Question, thn: PExp, c: PSymOp.Colon, val signatures: List[PTypeSubstitution] = List( Map(POpApp.pArgS(0) -> Bool, POpApp.pArgS(2) -> POpApp.pArg(1), POpApp.pResS -> POpApp.pArg(1)) ) + + override def reformatExp(ctx: ReformatterContext): Cont = show(cond, ctx) <+> show(q, ctx) <> + nest(defaultIndent, group(line <> show(thn, ctx) <+> + show(c, ctx) <> nest(defaultIndent, group(line <> show(els, ctx))))) } // Simple literals @@ -1033,9 +1114,13 @@ sealed trait PConstantLiteral extends PSimpleLiteral { case class PIntLit(i: BigInt)(val pos: (Position, Position)) extends PSimpleLiteral with PLeaf { typ = Int override def display = i.toString() + + override def reformatExp(ctx: ReformatterContext): Cont = text(i.toString) } -case class PResultLit(result: PKw.Result)(val pos: (Position, Position)) extends PSimpleLiteral +case class PResultLit(result: PKw.Result)(val pos: (Position, Position)) extends PSimpleLiteral { + override def reformatExp(ctx: ReformatterContext): Cont = show(result, ctx) +} case class PBoolLit(keyword: PReserved[PKeywordConstant])(val pos: (Position, Position)) extends PConstantLiteral { def b: Boolean = keyword.rs.keyword match { @@ -1043,10 +1128,14 @@ case class PBoolLit(keyword: PReserved[PKeywordConstant])(val pos: (Position, Po case PKw.False.keyword => false } typ = Bool + + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) } case class PNullLit(keyword: PKw.Null)(val pos: (Position, Position)) extends PConstantLiteral { typ = Ref + + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) } sealed trait PHeapOpApp extends POpApp @@ -1066,24 +1155,34 @@ case class PFieldAccess(rcv: PExp, dot: PSymOp.Dot, idnref: PIdnRef[PFieldDecl]) ) case _ => List() } + + override def reformatExp(ctx: ReformatterContext): Cont = show(rcv, ctx) <> show(dot, ctx) <> show(idnref, ctx) } case class PUnfolding(unfolding: PKwOp.Unfolding, acc: PAccAssertion, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { override val args = Seq(acc, exp) override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Predicate, POpApp.pResS -> POpApp.pArg(1))) + + override def reformatExp(ctx: ReformatterContext): Cont = show(unfolding, ctx) <+> show(acc, ctx) <+> show(in, ctx) <> nest(defaultIndent, group(line <> show(exp, ctx))) } case class PApplying(applying: PKwOp.Applying, wand: PExp, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { override val args = Seq(wand, exp) override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Wand, POpApp.pResS -> POpApp.pArg(1))) + + override def reformatExp(ctx: ReformatterContext): Cont = show(applying, ctx) <+> show(wand, ctx) <+> show(in, ctx) <> nest(defaultIndent, group(line <> show(exp, ctx))) } case class PAsserting(asserting: PKwOp.Asserting, a: PExp, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { override val args = Seq(a, exp) override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Impure, POpApp.pResS -> POpApp.pArg(1))) + + override def reformatExp(ctx: ReformatterContext): Cont = show(asserting, ctx) <+> + nest(defaultIndent, group(line <> show(a, ctx))) <+> + show(in, ctx) <> nest(defaultIndent, group(line <> show(exp, ctx))) } sealed trait PBinder extends PExp with PScope { @@ -1104,6 +1203,8 @@ sealed trait PBinder extends PExp with PScope { case class PTrigger(exp: PDelimited.Comma[PSym.Brace, PExp])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { override def pretty = exp.pretty + + override def reformat(ctx: ReformatterContext): Cont = show(exp, ctx) } sealed trait PQuantifier extends PBinder { @@ -1114,12 +1215,20 @@ sealed trait PQuantifier extends PBinder { override def boundVars = vars.toSeq } -case class PExists(keyword: PKw.Exists, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier +case class PExists(keyword: PKw.Exists, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier { + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> + show(vars, ctx) <+> show(c, ctx) <+> showSeq(triggers, ctx) <+> show(body, ctx) +} -case class PForall(keyword: PKw.Forall, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier +case class PForall(keyword: PKw.Forall, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier { + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> show(vars, ctx) <+> + show(c, ctx) <> nest(defaultIndent, group(line <> (showSeq(triggers, ctx) <+@> show(body, ctx)))) +} case class PForPerm(keyword: PKw.Forperm, vars: PDelimited[PLogicalVarDecl, PSym.Comma], accessRes: PGrouped[PSym.Bracket, PResourceAccess], c: PSym.ColonColon, body: PExp)(val pos: (Position, Position)) extends PQuantifier { val triggers: Seq[PTrigger] = Seq() + + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> show(vars, ctx) <+> show(accessRes, ctx) <+> show(c, ctx) <+> show(body, ctx) } /* Let-expressions `let x == e1 in e2` are represented by the nested structure @@ -1142,12 +1251,17 @@ case class PLet(l: PKwOp.Let, variable: PIdnDef, eq: PSymOp.EqEq, exp: PGrouped. nestedScope.body.forceSubstitution(ts) typ = nestedScope.body.typ } + + override def reformatExp(ctx: ReformatterContext): Cont = show(l, ctx) <+> show(variable, ctx) <+> + show(eq, ctx) <+> nest(defaultIndent, show(exp, ctx) <+> show(in, ctx) <@> show(nestedScope, ctx)) } case class PLetNestedScope(body: PExp)(val pos: (Position, Position)) extends PTypedVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { def outerLet: PLet = getAncestor[PLet].get override def idndef: PIdnDef = outerLet.variable override def typ: PType = outerLet.exp.inner.typ + + override def reformat(ctx: ReformatterContext): Cont = show(body, ctx) } // [in,ex] @@ -1158,14 +1272,21 @@ case class PInhaleExhaleExp(l: PSymOp.LBracket, in: PExp, c: PSymOp.Comma, ex: P Map(POpApp.pArgS(0) -> Bool, POpApp.pArgS(1) -> Bool, POpApp.pResS -> Bool), Map(POpApp.pArgS(0) -> Impure, POpApp.pArgS(1) -> Impure, POpApp.pResS -> Impure), ) + + override def reformatExp(ctx: ReformatterContext): Cont = show(l, ctx) <> + show(in, ctx) <> show(c, ctx) <+> show(ex, ctx) <> show(r, ctx) } case class PNoPerm(keyword: PKw.None)(val pos: (Position, Position)) extends PConstantLiteral { typ = Perm + + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) } case class PFullPerm(keyword: PKw.Write)(val pos: (Position, Position)) extends PConstantLiteral { typ = Perm + + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) } object PFullPerm { def implied(): PFullPerm = PFullPerm(PReserved(PKw.Write)(NoPosition, NoPosition))(NoPosition, NoPosition) @@ -1173,10 +1294,14 @@ object PFullPerm { case class PWildcard(keyword: PKw.Wildcard)(val pos: (Position, Position)) extends PConstantLiteral { typ = Perm + + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) } case class PEpsilon(keyword: PKw.Epsilon)(val pos: (Position, Position)) extends PConstantLiteral { typ = Perm + + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) } trait PCallKeyword extends POpApp { @@ -1188,10 +1313,16 @@ case class PCurPerm(op: PKwOp.Perm, res: PGrouped.Paren[PResourceAccess])(val po val signatures: List[PTypeSubstitution] = List( Map(POpApp.pResS -> Perm) ) + + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <+> show(res, ctx) } -case class PPairArgument[+T, +U](first: T, c: PSym.Comma, second: U)(val pos: (Position, Position)) extends PNode with PPrettySubnodes -case class PMaybePairArgument[+T, +U](first: T, second: Option[(PSym.Comma, U)])(val pos: (Position, Position)) extends PNode with PPrettySubnodes +case class PPairArgument[+T, +U](first: T, c: PSym.Comma, second: U)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { + override def reformat(ctx: ReformatterContext): Cont = showAny(first, ctx) <> show(c, ctx) <+> showAny(second, ctx) +} +case class PMaybePairArgument[+T, +U](first: T, second: Option[(PSym.Comma, U)])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { + override def reformat(ctx: ReformatterContext): Cont = showAny(first, ctx) <> second.map(a => show(a._1, ctx) <+> showAny(a._2, ctx)).getOrElse(nil) +} sealed trait PAccAssertion extends PExp { def loc: PLocationAccess @@ -1206,12 +1337,16 @@ case class PAccPred(op: PKwOp.Acc, amount: PGrouped.Paren[PMaybePairArgument[PLo def loc = amount.inner.first def perm = amount.inner.second.map(_._2).getOrElse(PFullPerm.implied()) override val args = Seq(loc, perm) + + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(amount, ctx) } case class POldExp(op: PKwOp.Old, label: Option[PGrouped[PSym.Bracket, Either[PKw.Lhs, PIdnRef[PLabel]]]], e: PGrouped.Paren[PExp])(val pos: (Position, Position)) extends PCallKeyword with PHeapOpApp { override val args = Seq(e.inner) override def requirePure = args override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pResS -> POpApp.pArg(0))) + + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> showOption(label, ctx) <> show(e, ctx) } case class PDebugLabelledOldExp(op: PKwOp.Old, label: PVersionedIdnUseExp, e: PExp)(val pos: (Position, Position)) extends PCallKeyword with PHeapOpApp { @@ -1220,6 +1355,8 @@ case class PDebugLabelledOldExp(op: PKwOp.Old, label: PVersionedIdnUseExp, e: PE override def requirePure = args override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pResS -> POpApp.pArg(0))) + + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(label, ctx) <> show(e, ctx) } sealed trait PCollectionLiteral extends PCallKeyword { @@ -1266,9 +1403,13 @@ sealed trait PSeqLiteral extends PCollectionLiteral { def pCollectionType(pType: PType) = if (pType.isUnknown) PUnknown() else MakeSeq(pType) } -case class PEmptySeq(op: PKwOp.Seq, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PSeqLiteral with PEmptyCollectionLiteral +case class PEmptySeq(op: PKwOp.Seq, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PSeqLiteral with PEmptyCollectionLiteral { + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <+> showOption(pAnnotatedType, ctx) <> show(callArgs, ctx) +} -case class PExplicitSeq(op: PKwOp.Seq, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PSeqLiteral with PExplicitCollectionLiteral +case class PExplicitSeq(op: PKwOp.Seq, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PSeqLiteral with PExplicitCollectionLiteral { + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <+> show(callArgs, ctx) +} // [low..high) case class PRangeSeq(l: PSymOp.LBracket, low: PExp, ds: PSymOp.DotDot, high: PExp, r: PSymOp.RParen)(val pos: (Position, Position)) extends POpApp { @@ -1276,6 +1417,9 @@ case class PRangeSeq(l: PSymOp.LBracket, low: PExp, ds: PSymOp.DotDot, high: PEx override val signatures: List[PTypeSubstitution] = List( Map(POpApp.pArgS(0) -> Int, POpApp.pArgS(1) -> Int, POpApp.pResS -> MakeSeq(Int))) + + override def reformatExp(ctx: ReformatterContext): Cont = show(l, ctx) <> show(low, ctx) <> show(ds, ctx) <> + show(high, ctx) <> show(r, ctx) } // base[idx] @@ -1289,6 +1433,9 @@ case class PLookup(base: PExp, l: PSymOp.LBracket, idx: PExp, r: PSymOp.RBracket Map(POpApp.pArgS(0) -> MakeSeq(POpApp.pRes), POpApp.pArgS(1) -> Int), Map(POpApp.pArgS(0) -> MakeMap(keyType, POpApp.pRes)) ) + + override def reformatExp(ctx: ReformatterContext): Cont = show(base, ctx) <> show(l, ctx) <> + show(idx, ctx) <> show(r, ctx) } case class PSeqSlice(seq: PExp, l: PSymOp.LBracket, s: Option[PExp], d: PSymOp.DotDot, e: Option[PExp], r: PSymOp.RBracket)(val pos: (Position, Position)) extends POpApp { @@ -1303,6 +1450,9 @@ case class PSeqSlice(seq: PExp, l: PSymOp.LBracket, s: Option[PExp], d: PSymOp.D case (Some(_), None) | (None, Some(_)) => Map(POpApp.pArgS(1) -> Int) case (None, None) => Map() })) + + override def reformatExp(ctx: ReformatterContext): Cont = show(seq, ctx) <> show(l, ctx) <> + showOption(s, ctx) <> show(d, ctx) <> showOption(e, ctx) <> show(r, ctx) } case class PUpdate(base: PExp, l: PSymOp.LBracket, key: PExp, a: PSymOp.Assign, value: PExp, r: PSymOp.RBracket)(val pos: (Position, Position)) extends POpApp { @@ -1316,6 +1466,9 @@ case class PUpdate(base: PExp, l: PSymOp.LBracket, key: PExp, a: PSymOp.Assign, Map(POpApp.pArgS(0) -> MakeSeq(elementType), POpApp.pArgS(1) -> Int, POpApp.pResS -> MakeSeq(elementType)), Map(POpApp.pArgS(0) -> MakeMap(keyType, elementType), POpApp.pResS -> MakeMap(keyType, elementType)) ) + + override def reformatExp(ctx: ReformatterContext): Cont = show(base, ctx) <> show(l, ctx) <> + show(key, ctx) <+> show(a, ctx) <+> show(value, ctx) <> show(r, ctx) } case class PSize(l: PSymOp.Or, seq: PExp, r: PSymOp.Or)(val pos: (Position, Position)) extends POpApp { @@ -1332,23 +1485,37 @@ case class PSize(l: PSymOp.Or, seq: PExp, r: PSymOp.Or)(val pos: (Position, Posi Map(POpApp.pArgS(0) -> MakeMultiset(elementType), POpApp.pResS -> Int), Map(POpApp.pArgS(0) -> MakeMap(keyType, elementType), POpApp.pResS -> Int) ) + + override def reformatExp(ctx: ReformatterContext): Cont = show(l, ctx) <> + show(seq, ctx) <> show(r, ctx) } sealed trait PSetLiteral extends PCollectionLiteral { def pCollectionType(pType: PType) = if (pType.isUnknown) PUnknown() else MakeSet(pType) } -case class PEmptySet(op: PKwOp.Set, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PSetLiteral with PEmptyCollectionLiteral +case class PEmptySet(op: PKwOp.Set, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PSetLiteral with PEmptyCollectionLiteral { + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> + showOption(pAnnotatedType, ctx) <> show(callArgs, ctx) +} -case class PExplicitSet(op: PKwOp.Set, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PSetLiteral with PExplicitCollectionLiteral +case class PExplicitSet(op: PKwOp.Set, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PSetLiteral with PExplicitCollectionLiteral { + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(callArgs, ctx) +} sealed trait PMultiSetLiteral extends PCollectionLiteral { def pCollectionType(pType: PType) = if (pType.isUnknown) PUnknown() else MakeMultiset(pType) } -case class PEmptyMultiset(op: PKwOp.Multiset, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PMultiSetLiteral with PEmptyCollectionLiteral +case class PEmptyMultiset(op: PKwOp.Multiset, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PMultiSetLiteral with PEmptyCollectionLiteral { + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> + showOption(pAnnotatedType, ctx) <> show(callArgs, ctx) +} -case class PExplicitMultiset(op: PKwOp.Multiset, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PMultiSetLiteral with PExplicitCollectionLiteral +case class PExplicitMultiset(op: PKwOp.Multiset, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PMultiSetLiteral with PExplicitCollectionLiteral { + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> + show(callArgs, ctx) +} /* ** Maps */ @@ -1377,6 +1544,9 @@ case class PEmptyMap(op: PKwOp.Map, pAnnotatedType: Option[PGrouped[PSym.Bracket )) def explicitType: Option[(PType, PType)] = pAnnotatedType.map(t => (t.inner.first, t.inner.second)) + + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> + showOption(pAnnotatedType, ctx) <> show(callArgs, ctx) } case class PExplicitMap(op: PKwOp.Map, callArgs: PDelimited.Comma[PSym.Paren, PMaplet])(val pos: (Position, Position)) extends PMapLiteral { @@ -1389,6 +1559,8 @@ case class PExplicitMap(op: PKwOp.Map, callArgs: PDelimited.Comma[PSym.Paren, PM case n => POpApp.pArgS(n) -> POpApp.pArg(0) }.toMap ) + + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(callArgs, ctx) } /** @@ -1400,6 +1572,8 @@ case class PMaplet(key: PExp, a: PSymOp.Assign, value: PExp)(val pos: (Position, override def signatures: List[PTypeSubstitution] = List(Map( POpApp.pResS -> MakeMap(POpApp.pArg(0), POpApp.pArg(1)) )) + + override def reformatExp(ctx: ReformatterContext): Cont = show(key, ctx) <+> show(a, ctx) <+> show(value, ctx) } case class PMapDomain(keyword: PKwOp.Domain, base: PGrouped.Paren[PExp])(val pos: (Position, Position)) extends POpApp { @@ -1413,6 +1587,8 @@ case class PMapDomain(keyword: PKwOp.Domain, base: PGrouped.Paren[PExp])(val pos POpApp.pArgS(0) -> MakeMap(keyType, valueType), POpApp.pResS -> MakeSet(keyType) )) + + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <> show(base, ctx) } case class PMapRange(keyword: PKwOp.Range, base: PGrouped.Paren[PExp])(val pos: (Position, Position)) extends POpApp { @@ -1426,6 +1602,8 @@ case class PMapRange(keyword: PKwOp.Range, base: PGrouped.Paren[PExp])(val pos: POpApp.pArgS(0) -> MakeMap(keyType, valueType), POpApp.pResS -> MakeSet(valueType) )) + + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <> show(base, ctx) } @@ -1433,10 +1611,14 @@ case class PMapRange(keyword: PKwOp.Range, base: PGrouped.Paren[PExp])(val pos: // Statements trait PStmt extends PNode with PPrettySubnodes -case class PAnnotatedStmt(annotation: PAnnotation, stmt: PStmt)(val pos: (Position, Position)) extends PStmt +case class PAnnotatedStmt(annotation: PAnnotation, stmt: PStmt)(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(annotation, ctx) <@@> show(stmt, ctx) +} case class PSeqn(ss: PDelimited.Block[PStmt])(val pos: (Position, Position)) extends PStmt with PScope { override def pretty = ss.prettyLines + + override def reformat(ctx: ReformatterContext): Cont = show(ss, ctx) } /** @@ -1445,56 +1627,108 @@ case class PSeqn(ss: PDelimited.Block[PStmt])(val pos: (Position, Position)) ext * Is created only temporarily during macro expansion and eliminated (i.e., expanded into the surrounding scope) * before translation. */ -case class PMacroSeqn(ss: PDelimited.Block[PStmt])(val pos: (Position, Position)) extends PStmt +case class PMacroSeqn(ss: PDelimited.Block[PStmt])(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(ss, ctx) +} -case class PFold(fold: PKw.Fold, e: PExp)(val pos: (Position, Position)) extends PStmt +case class PFold(fold: PKw.Fold, e: PExp)(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(fold, ctx) <+> show(e, ctx) +} -case class PUnfold(unfold: PKw.Unfold, e: PExp)(val pos: (Position, Position)) extends PStmt +case class PUnfold(unfold: PKw.Unfold, e: PExp)(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(unfold, ctx) <+> show(e, ctx) +} -case class PPackageWand(pckg: PKw.Package, e: PExp, proofScript: Option[PSeqn])(val pos: (Position, Position)) extends PStmt +case class PPackageWand(pckg: PKw.Package, e: PExp, proofScript: Option[PSeqn])(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(pckg, ctx) <+> show(e, ctx) <+> + showOption(proofScript, ctx) +} -case class PApplyWand(apply: PKw.Apply, e: PExp)(val pos: (Position, Position)) extends PStmt +case class PApplyWand(apply: PKw.Apply, e: PExp)(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(apply, ctx) <+> show(e, ctx) +} -case class PExhale(exhale: PKw.Exhale, e: PExp)(val pos: (Position, Position)) extends PStmt +case class PExhale(exhale: PKw.Exhale, e: PExp)(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(exhale, ctx) <+> show(e, ctx) +} -case class PAssert(assert: PKw.Assert, e: PExp)(val pos: (Position, Position)) extends PStmt +case class PAssert(assert: PKw.Assert, e: PExp)(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(assert, ctx) <+> show(e, ctx) +} -case class PAssume(assume: PKw.Assume, e: PExp)(val pos: (Position, Position)) extends PStmt +case class PAssume(assume: PKw.Assume, e: PExp)(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(assume, ctx) <+> show(e, ctx) +} -case class PInhale(inhale: PKw.Inhale, e: PExp)(val pos: (Position, Position)) extends PStmt +case class PInhale(inhale: PKw.Inhale, e: PExp)(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(inhale, ctx) <+> show(e, ctx) +} /** Can also represent a method call or statement macro with no `:=` when `targets` is empty. */ -case class PAssign(targets: PDelimited[PExp with PAssignTarget, PSym.Comma], op: Option[PSymOp.Assign], rhs: PExp)(val pos: (Position, Position)) extends PStmt +case class PAssign(targets: PDelimited[PExp with PAssignTarget, PSym.Comma], op: Option[PSymOp.Assign], rhs: PExp)(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(targets, ctx) <+@> showOption(op, ctx) <+@> nest(defaultIndent, show(rhs, ctx)) +} sealed trait PIfContinuation extends PStmt -case class PIf(keyword: PReserved[PKeywordIf], cond: PGrouped.Paren[PExp], thn: PSeqn, els: Option[PIfContinuation])(val pos: (Position, Position)) extends PStmt with PIfContinuation -case class PElse(k: PKw.Else, els: PSeqn)(val pos: (Position, Position)) extends PStmt with PIfContinuation +case class PIf(keyword: PReserved[PKeywordIf], cond: PGrouped.Paren[PExp], thn: PSeqn, els: Option[PIfContinuation])(val pos: (Position, Position)) extends PStmt with PIfContinuation { + override def reformat(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> show(cond, ctx) <> + showBody(show(thn, ctx), true) <+@> showBody(showOption(els, ctx), false) -case class PWhile(keyword: PKw.While, cond: PGrouped.Paren[PExp], invs: PDelimited[PSpecification[PKw.InvSpec], Option[PSym.Semi]], body: PSeqn)(val pos: (Position, Position)) extends PStmt +} +case class PElse(k: PKw.Else, els: PSeqn)(val pos: (Position, Position)) extends PStmt with PIfContinuation { + override def reformat(ctx: ReformatterContext): Cont = { + show(k, ctx) <+> showBody(show(els, ctx), false) + } +} + +case class PWhile(keyword: PKw.While, cond: PGrouped.Paren[PExp], invs: PDelimited[PSpecification[PKw.InvSpec], Option[PSym.Semi]], body: PSeqn)(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = { + show(keyword, ctx) <> show(cond, ctx) <+> + showInvs(invs, ctx) <> showBody(show(body, ctx), !invs.isEmpty) + } +} case class PVars(keyword: PKw.Var, vars: PDelimited[PLocalVarDecl, PSym.Comma], init: Option[(PSymOp.Assign, PExp)])(val pos: (Position, Position)) extends PStmt { def assign: Option[PAssign] = init map (i => PAssign(vars.update(vars.toSeq.map(_.toIdnUse)), Some(i._1), i._2)(pos)) + + override def reformat(ctx: ReformatterContext): Cont = + show(keyword, ctx) <+> show(vars, ctx) <> + init.map(s => nest(defaultIndent, group(nil <+> show(s._1, ctx) <@> show(s._2, ctx)))).getOrElse(nil) } -case class PLabel(label: PKw.Label, idndef: PIdnDef, invs: PDelimited[PSpecification[PKw.InvSpec], Option[PSym.Semi]])(val pos: (Position, Position)) extends PStmt with PMemberDeclaration with PBackwardDeclaration +case class PLabel(label: PKw.Label, idndef: PIdnDef, invs: PDelimited[PSpecification[PKw.InvSpec], Option[PSym.Semi]])(val pos: (Position, Position)) extends PStmt with PMemberDeclaration with PBackwardDeclaration { + override def reformat(ctx: ReformatterContext): Cont = show(label, ctx) <+> show(idndef, ctx) <+> show(invs, ctx) +} -case class PGoto(goto: PKw.Goto, target: PIdnRef[PLabel])(val pos: (Position, Position)) extends PStmt +case class PGoto(goto: PKw.Goto, target: PIdnRef[PLabel])(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(goto, ctx) <+> show(target, ctx) +} // Should this be sealed? sealed trait PTypeDeclaration extends PDeclarationInner -case class PTypeVarDecl(idndef: PIdnDef)(val pos: (Position, Position)) extends PMemberDeclaration with PTypeDeclaration with PPrettySubnodes +case class PTypeVarDecl(idndef: PIdnDef)(val pos: (Position, Position)) extends PMemberDeclaration with PTypeDeclaration with PPrettySubnodes { + override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) +} -case class PSkip()(val pos: (Position, Position)) extends PStmt +case class PSkip()(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = text("") +} -case class PQuasihavoc(quasihavoc: PKw.Quasihavoc, lhs: Option[(PExp, PSymOp.Implies)], e: PExp)(val pos: (Position, Position)) extends PStmt +case class PQuasihavoc(quasihavoc: PKw.Quasihavoc, lhs: Option[(PExp, PSymOp.Implies)], e: PExp)(val pos: (Position, Position)) extends PStmt { + override def reformat(ctx: ReformatterContext): Cont = show(quasihavoc, ctx) <+@> showOption(lhs, ctx) <+@> show(e, ctx) +} -case class PQuasihavocall(quasihavocall: PKw.Quasihavocall, vars: PDelimited[PLogicalVarDecl, PSym.Comma], colons: PSym.ColonColon, lhs: Option[(PExp, PSymOp.Implies)], e: PExp)(val pos: (Position, Position)) extends PStmt with PScope +case class PQuasihavocall(quasihavocall: PKw.Quasihavocall, vars: PDelimited[PLogicalVarDecl, PSym.Comma], colons: PSym.ColonColon, lhs: Option[(PExp, PSymOp.Implies)], e: PExp)(val pos: (Position, Position)) extends PStmt with PScope { + override def reformat(ctx: ReformatterContext): Cont = show(quasihavocall, ctx) <+@> showOption(lhs, ctx) <+@> show(e, ctx) +} /* new(f1, ..., fn) or new(*) */ case class PNewExp(keyword: PKw.New, fields: PGrouped.Paren[Either[PSym.Star, PDelimited[PIdnRef[PFieldDecl], PSym.Comma]]])(val pos: (Position, Position)) extends PExp { override final val typeSubstitutions = Seq(PTypeSubstitution.id) def forceSubstitution(ts: PTypeSubstitution) = {} + + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <> show(fields, ctx) } sealed trait PScope extends PNode { @@ -1566,6 +1800,8 @@ trait PTypedDeclaration extends PUnnamedTypedDeclaration case class PBracedExp(e: PGrouped[PSym.Brace, PExp])(val pos: (Position, Position)) extends PNode { override def pretty = s" ${e.l.pretty}\n ${e.inner.pretty.replace("\n", "\n ")}\n${e.r.pretty}" + + override def reformat(ctx: ReformatterContext): Cont = show(e, ctx) } trait PCallable extends PDeclarationInner { @@ -1616,7 +1852,7 @@ trait PNoSpecsFunction extends PAnyFunction { /////////////////////////////////////////////////////////////////////////// // Program Members -case class PProgram(imported: Seq[PProgram], members: Seq[PMember])(val pos: (Position, Position), val localErrors: Seq[ParseReport]) extends PNode { +case class PProgram(imported: Seq[PProgram], members: Seq[PMember])(val pos: (Position, Position), val localErrors: Seq[ParseReport], var offsets: Seq[Int], var rawProgram: String) extends PNode { val imports: Seq[PImport] = members.collect { case i: PImport => i } ++ imported.flatMap(_.imports) val macros: Seq[PDefine] = members.collect { case m: PDefine => m } ++ imported.flatMap(_.macros) val domains: Seq[PDomain] = members.collect { case d: PDomain => d } ++ imported.flatMap(_.domains) @@ -1633,91 +1869,182 @@ case class PProgram(imported: Seq[PProgram], members: Seq[PMember])(val pos: (Po val i = imported.map(_.pretty).mkString("\n") prefix + m + "\n\n" + i } + + override def reformat(ctx: ReformatterContext): Cont = { + println(s"whole program ${this.members}"); + members.map(show(_, ctx)).foldLeft(nil)((acc, n) => acc <@@> n) <> + // Don't forget comments that appear after any nodes! + formatTrivia(ctx.getTriviaByByteOffset(rawProgram.length), ctx) + } + // Pretty print members in a specific order def prettyOrdered: String = { val all = Seq(imports, macros, domains, fields, functions, predicates, methods, extensions).filter(_.length > 0) all.map(_.map(_.pretty).mkString("\n")).mkString("\n") } - override def getExtraVals: Seq[Any] = Seq(pos, localErrors) + override def getExtraVals: Seq[Any] = Seq(pos, localErrors, offsets, rawProgram) - def filterMembers(f: PMember => Boolean): PProgram = PProgram(imported.map(_.filterMembers(f)), members.filter(f))(pos, localErrors) - def newImported(newImported: Seq[PProgram]): PProgram = if (newImported.isEmpty) this else PProgram(imported ++ newImported, members)(pos, localErrors) + def filterMembers(f: PMember => Boolean): PProgram = PProgram(imported.map(_.filterMembers(f)), members.filter(f))(pos, localErrors, offsets, rawProgram) + def newImported(newImported: Seq[PProgram]): PProgram = if (newImported.isEmpty) this else PProgram(imported ++ newImported, members)(pos, localErrors, offsets, rawProgram) } object PProgram { - def error(error: ParseReport): PProgram = PProgram(Nil, Nil)((error.pos, error.pos), Seq(error)) + def error(error: ParseReport): PProgram = PProgram(Nil, Nil)((error.pos, error.pos), Seq(error), Nil, "") } case class PImport(annotations: Seq[PAnnotation], imprt: PKw.Import, file: PStringLiteral)(val pos: (FilePosition, FilePosition)) extends PMember with PPrettySubnodes { var local: Boolean = true var resolved: Option[Path] = None def declares = Nil + + override def reformat(ctx: ReformatterContext): Cont = show(imprt, ctx) <+> show(file, ctx) } -case class PDefineParam(idndef: PIdnDef)(val pos: (Position, Position)) extends PNode with PLocalDeclaration with PPrettySubnodes +case class PDefineParam(idndef: PIdnDef)(val pos: (Position, Position)) extends PNode with PLocalDeclaration with PPrettySubnodes { + override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) +} -case class PDefine(annotations: Seq[PAnnotation], define: PKw.Define, idndef: PIdnDef, parameters: Option[PDelimited.Comma[PSym.Paren, PDefineParam]], body: PNode)(val pos: (FilePosition, FilePosition)) extends PSingleMember with PStmt with PNameAnalyserOpaque +case class PDefine(annotations: Seq[PAnnotation], define: PKw.Define, idndef: PIdnDef, parameters: Option[PDelimited.Comma[PSym.Paren, PDefineParam]], body: PNode)(val pos: (FilePosition, FilePosition)) extends PSingleMember with PStmt with PNameAnalyserOpaque { + override def reformat(ctx: ReformatterContext): Cont = { + showAnnotations(annotations, ctx) <@@> show(define, ctx) <+> show(idndef, ctx) <> showOption(parameters, ctx) <+> show(body, ctx) + } +} case class PDomain(annotations: Seq[PAnnotation], domain: PKw.Domain, idndef: PIdnDef, typVars: Option[PDelimited.Comma[PSym.Bracket, PTypeVarDecl]], interpretations: Option[PDomainInterpretations], members: PGrouped[PSym.Brace, PDomainMembers]) (val pos: (Position, Position)) extends PSingleMember with PTypeDeclaration with PPrettySubnodes { def typVarsSeq: Seq[PTypeVarDecl] = typVars.map(_.inner.toSeq).getOrElse(Nil) + + override def reformat(ctx: ReformatterContext): Cont = { + showAnnotations(annotations, ctx) <@@> show(domain, ctx) <+> + show(idndef, ctx) <> showOption(typVars, ctx) <> + (if (interpretations.isEmpty) nil else nest(defaultIndent, linebreak <> showOption(interpretations, ctx))) <> + showBody(show(members, ctx), !interpretations.isEmpty) + } } case class PDomainFunctionInterpretation(k: PKw.Interpretation, i: PStringLiteral)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { override def pretty = s"\n ${super.pretty}" + + override def reformat(ctx: ReformatterContext): Cont = show(k, ctx) <+> show(i, ctx) } trait PDomainMember extends PScope { def domain: PDomain = getAncestor[PDomain].get } case class PDomainFunction(annotations: Seq[PAnnotation], unique: Option[PKw.Unique], keyword: PKw.FunctionD, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PDomainFunctionArg], c: PSym.Colon, resultType: PType, interpretation: Option[PDomainFunctionInterpretation])(val pos: (Position, Position)) extends PSingleMember with PNoSpecsFunction with PDomainMember with PPrettySubnodes { override def body = None + + override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> showOption(unique, ctx) <+@> + show(keyword, ctx) <+> show(idndef, ctx) <+> show(args, ctx) <> + show(c, ctx) <+> show(resultType, ctx) <+> showOption(interpretation, ctx) } -case class PAxiom(annotations: Seq[PAnnotation], axiom: PKw.Axiom, idndef: Option[PIdnDef], exp: PBracedExp)(val pos: (Position, Position)) extends PDomainMember with PPrettySubnodes -case class PDomainMembers(funcs: PDelimited[PDomainFunction, Option[PSym.Semi]], axioms: PDelimited[PAxiom, Option[PSym.Semi]])(val pos: (Position, Position)) extends PNode { +case class PAxiom(annotations: Seq[PAnnotation], axiom: PKw.Axiom, idndef: Option[PIdnDef], exp: PBracedExp)(val pos: (Position, Position)) extends PDomainMember with PPrettySubnodes { + override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> show(axiom, ctx) <+> + showOption(idndef, ctx) <+> show(exp, ctx) +} +case class PDomainMembers(funcs: PDelimited[PDomainFunction, Option[PSym.Semi]], axioms: PDelimited[PAxiom, Option[PSym.Semi]])(val pos: (Position, Position), val original: PDomainMembers1) extends PNode { override def pretty: String = { val fPretty = if (funcs.length == 0) "" else s"\n ${funcs.prettyLines.replace("\n", "\n ")}\n" val aPretty = if (axioms.length == 0) "" else s"\n ${axioms.prettyLines.replace("\n", "\n ")}\n" s"${fPretty}${aPretty}" } + + override def getExtraVals: Seq[Any] = Seq(pos, original) + + override def reformat(ctx: ReformatterContext): Cont = show(original, ctx) } -case class PDomainInterpretation(name: PRawString, c: PSym.Colon, lit: PStringLiteral)(val pos: (Position, Position)) extends PNode with PPrettySubnodes +case class PDomainInterpretation(name: PRawString, c: PSym.Colon, lit: PStringLiteral)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { + override def reformat(ctx: ReformatterContext): Cont = show(name, ctx) <> show(c, ctx) <+> show(lit, ctx) +} case class PDomainInterpretations(k: PReserved[PKeywordLang], m: PDelimited.Comma[PSym.Paren, PDomainInterpretation])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { def interps: Map[String, String] = m.inner.toSeq.map(i => i.name.str -> i.lit.str).toMap + + override def reformat(ctx: ReformatterContext): Cont = show(k, ctx) <+> show(m, ctx) } trait PDomainMember1 extends PNode with PPrettySubnodes -case class PDomainFunction1(annotations: Seq[PAnnotation], unique: Option[PKw.Unique], function: PKw.FunctionD, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PDomainFunctionArg], c: PSym.Colon, typ: PType, interpretation: Option[PDomainFunctionInterpretation], s: Option[PSym.Semi])(val pos: (Position, Position)) extends PDomainMember1 -case class PAxiom1(annotations: Seq[PAnnotation], axiom: PKw.Axiom, idndef: Option[PIdnDef], exp: PBracedExp, s: Option[PSym.Semi])(val pos: (Position, Position)) extends PDomainMember1 -case class PDomainMembers1(members: Seq[PDomainMember1])(val pos: (Position, Position)) extends PNode with PPrettySubnodes +case class PDomainFunction1(annotations: Seq[PAnnotation], unique: Option[PKw.Unique], function: PKw.FunctionD, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PDomainFunctionArg], c: PSym.Colon, typ: PType, interpretation: Option[PDomainFunctionInterpretation], s: Option[PSym.Semi])(val pos: (Position, Position)) extends PDomainMember1 { + override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> showOption(unique, ctx) <+@> + show(function, ctx) <+@> showOption(interpretation, ctx) <+> + show(idndef, ctx) <> show(args, ctx) <> show(c, ctx) <+> show(typ, ctx) <+> showOption(s, ctx) +} +case class PAxiom1(annotations: Seq[PAnnotation], axiom: PKw.Axiom, idndef: Option[PIdnDef], exp: PBracedExp, s: Option[PSym.Semi])(val pos: (Position, Position)) extends PDomainMember1 { + override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> show(axiom, ctx) <+@> + showOption(idndef, ctx) <+@> show(exp, ctx) <> showOption(s, ctx) +} +case class PDomainMembers1(members: Seq[PDomainMember1])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { + override def reformat(ctx: ReformatterContext): Cont = if (members.isEmpty) nil else members.map(m => show(m, ctx)) + .reduce(_ <> linebreak <> _) +} case class PFields(annotations: Seq[PAnnotation], field: PKw.Field, fields: PDelimited[PFieldDecl, PSym.Comma], s: Option[PSym.Semi])(val pos: (Position, Position)) extends PMember with PPrettySubnodes { override def declares: Seq[PGlobalDeclaration] = fields.toSeq + + override def reformat(ctx: ReformatterContext): Cont = { + // println(s"PFields"); + // println(s"---------------------------"); + // println(s"annotation: ${annotation}"); + // println(s"field: ${field}"); + // println(s"fields: ${fields}"); + // println(s"s: ${s}"); + show(field, ctx) <+> show(fields, ctx) <> showOption(s, ctx) + } } case class PSpecification[+T <: PKw.Spec](k: PReserved[PKw.Spec], e: PExp)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { override def pretty: String = "\n " + super.pretty + + override def reformat(ctx: ReformatterContext): Cont = show(k, ctx) <+> show(e, ctx) } case class PFunction(annotations: Seq[PAnnotation], keyword: PKw.Function, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PFormalArgDecl], c: PSym.Colon, resultType: PType, pres: PDelimited[PSpecification[PKw.PreSpec], Option[PSym.Semi]], posts: PDelimited[PSpecification[PKw.PostSpec], Option[PSym.Semi]], body: Option[PBracedExp]) - (val pos: (Position, Position)) extends PSingleMember with PAnyFunction with PGlobalCallableNamedArgs with PPrettySubnodes + (val pos: (Position, Position)) extends PSingleMember with PAnyFunction with PGlobalCallableNamedArgs with PPrettySubnodes { + override def reformat(ctx: ReformatterContext): Cont = { + // TODO: Add PFunctioNType + println(s"PFunction"); + println(s"---------------------------"); + println(s"body ${body}"); + showAnnotations(annotations, ctx) <@@> show(keyword, ctx) <+> show(idndef, ctx) <> + show(args, ctx) <+> show(c, ctx) <+> show(resultType, ctx) <> + showPresPosts(pres, posts, ctx) <> showBody(showOption(body, ctx), !(pres.isEmpty && posts.isEmpty)) + } +} case class PPredicate(annotations: Seq[PAnnotation], keyword: PKw.Predicate, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PFormalArgDecl], body: Option[PBracedExp])(val pos: (Position, Position)) extends PSingleMember with PNoSpecsFunction with PGlobalCallableNamedArgs with PPrettySubnodes { override def c = PReserved.implied(PSym.Colon) override def resultType = Predicate + + override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> show(keyword, ctx) <+> show(idndef, ctx) <> + show(args, ctx) <> showBody(showOption(body, ctx), false) } case class PMethod(annotations: Seq[PAnnotation], keyword: PKw.Method, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PFormalArgDecl], returns: Option[PMethodReturns], pres: PDelimited[PSpecification[PKw.PreSpec], Option[PSym.Semi]], posts: PDelimited[PSpecification[PKw.PostSpec], Option[PSym.Semi]], body: Option[PSeqn]) (val pos: (Position, Position)) extends PSingleMember with PGlobalCallableNamedArgs with PPrettySubnodes { def formalReturns: Seq[PFormalReturnDecl] = returns.map(_.formalReturns.inner.toSeq).getOrElse(Nil) override def returnNodes = returns.toSeq + + override def reformat(ctx: ReformatterContext): Cont = { + // TODO: Test annotations +// println(s"PMethod"); +// println(s"---------------------------"); +// println(s"args ${args}"); +// println(s"returns ${returns}"); +// println(s"pres ${pres}"); +// println(s"posts ${posts}"); +// println(s"body ${body}"); +// println(s"keyword pos: ${keyword.pos}"); + showAnnotations(annotations, ctx) <@@> show(keyword, ctx) <+> show(idndef, ctx) <> show(args, ctx) <> showReturns(returns, ctx) <> + showPresPosts(pres, posts, ctx) <> showBody(showOption(body, ctx), !(returns.isEmpty && pres.isEmpty && posts.isEmpty)) + } } -case class PMethodReturns(k: PKw.Returns, formalReturns: PGrouped.Paren[PDelimited[PFormalReturnDecl, PSym.Comma]])(val pos: (Position, Position)) extends PNode with PPrettySubnodes +case class PMethodReturns(k: PKw.Returns, formalReturns: PGrouped.Paren[PDelimited[PFormalReturnDecl, PSym.Comma]])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { + override def reformat(ctx: ReformatterContext): Cont = show(k, ctx) <+> show(formalReturns, ctx) +} /** * Used for parsing annotation for top level members. Passed as an argument to the members to construct them. @@ -1726,16 +2053,22 @@ case class PAnnotationsPosition(annotations: Seq[PAnnotation], pos: (FilePositio case class PAnnotation(at: PSym.At, key: PRawString, values: PGrouped.Paren[PDelimited[PStringLiteral, PSym.Comma]])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { override def pretty: String = super.pretty + "\n" + + override def reformat(ctx: ReformatterContext): Cont = show(at, ctx) <> show(key, ctx) <> show(values, ctx) } // Any unenclosed string (e.g. `hello`) case class PRawString(str: String)(val pos: (Position, Position)) extends PNode with PLeaf { override def display: String = str + + override def reformat(ctx: ReformatterContext): Cont = text(str) } // Any enclosed string (e.g. `"hello"`) case class PStringLiteral(grouped: PGrouped[_, PRawString])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { def str: String = grouped.inner.str + + override def reformat(ctx: ReformatterContext): Cont = show(grouped, ctx) } trait PExtender extends PNode { @@ -1752,4 +2085,27 @@ trait PExtender extends PNode { def translateExp(t: Translator): Exp = ??? def translateType(t: Translator): Type = ??? +} + +// Trivia (comments, whitespaces) +trait Trivia extends Reformattable + +case class POther() extends Trivia { + override def reformat(ctx: ReformatterContext): Cont = "" +} + +case class PSpace() extends Trivia { + override def reformat(ctx: ReformatterContext): Cont = space +} + +case class PNewLine() extends Trivia { + override def reformat(ctx: ReformatterContext): Cont = linebreak +} + +case class PComment(content: String, block: Boolean) extends Trivia { + override def reformat(ctx: ReformatterContext): Cont = if (block) { + text("/*") <> content <> text("*/") <> linebreak + } else { + text("//") <> text(content) <> linebreak + } } \ No newline at end of file diff --git a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala index daed9a67f..9a47bf298 100644 --- a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala +++ b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala @@ -7,6 +7,8 @@ package viper.silver.parser import viper.silver.ast.{NoPosition, Position} +import viper.silver.parser.PSym.Brace +import viper.silver.parser.ReformatPrettyPrinter.{show, showAny} import viper.silver.parser.TypeHelper._ trait PReservedString { @@ -17,8 +19,12 @@ trait PReservedString { } trait LeftSpace extends PReservedString { override def leftPad = " " } trait RightSpace extends PReservedString { override def rightPad = " " } +trait LeftNewlineIndent extends PReservedString { override def leftPad = "\n " } case class PReserved[+T <: PReservedString](rs: T)(val pos: (Position, Position)) extends PNode with PLeaf { override def display = rs.display + def token = rs.token + + override def reformat(ctx: ReformatterContext): Cont = text(token) } object PReserved { def implied[T <: PReservedString](rs: T): PReserved[T] = PReserved(rs)(NoPosition, NoPosition) @@ -31,6 +37,21 @@ case class PGrouped[G <: PSym.Group, +T](l: PReserved[G#L], inner: T, r: PReserv val iPretty = if (inner.length == 0) "" else s"\n ${inner.prettyLines.replace("\n", "\n ")}\n" s"${l.pretty}${iPretty}${r.pretty}" } + + override def reformat(ctx: ReformatterContext): Cont = { + if (l.rs.isInstanceOf[Brace]) { + val left = show(l, ctx); + val inner_ = showAny(inner, ctx); + val right = show(r, ctx); + if (inner_ == nil) { + left <> right + } else { + left <> nest(defaultIndent, line <> inner_) <> line <> right + } + } else { + show(l, ctx) <> nest(defaultIndent, showAny(inner, ctx)) <> show(r, ctx) + } + } } object PGrouped { /** Grouped and delimited. */ @@ -83,6 +104,24 @@ class PDelimited[+T, +D]( } override def hashCode(): Int = viper.silver.utility.Common.generateHashCode(first, inner, end) override def toString(): String = s"PDelimited($first,$inner,$end)" + + override def reformat(ctx: ReformatterContext): Cont = { +// println(s"PDelimited"); +// println(s"---------------------------"); +// println(s"first: ${first}"); +// println(s"inner: ${inner}"); +// println(s"end: ${end}"); + + val separator = delimiters.headOption match { + case Some(p: PSym.Comma) => space + case None => nil + case _ => line + }; + + showAny(first, ctx) <@@@> + inner.foldLeft(nil)((acc, b) => acc <@@@> showAny(b._1, ctx) <@@@> separator <@@@> showAny(b._2, ctx)) <@@@> + showAny(end, ctx) + } } object PDelimited { @@ -129,7 +168,10 @@ sealed trait PKeywordAtom sealed trait PKeywordIf extends PKeywordStmt -abstract class PKw(val keyword: String) extends PKeyword +abstract class PKw(val keyword: String) extends PKeyword with Reformattable { + override def reformat(ctx: ReformatterContext): Cont = text(keyword) +} + object PKw { case object Import extends PKw("import") with PKeywordLang type Import = PReserved[Import.type] @@ -159,11 +201,11 @@ object PKw { sealed trait Spec extends PReservedString; trait AnySpec extends PreSpec with PostSpec with InvSpec trait PreSpec extends Spec; trait PostSpec extends Spec; trait InvSpec extends Spec - case object Requires extends PKw("requires") with PKeywordLang with PreSpec + case object Requires extends PKw("requires") with PKeywordLang with PreSpec with LeftNewlineIndent type Requires = PReserved[Requires.type] - case object Ensures extends PKw("ensures") with PKeywordLang with PostSpec + case object Ensures extends PKw("ensures") with PKeywordLang with PostSpec with LeftNewlineIndent type Ensures = PReserved[Ensures.type] - case object Invariant extends PKw("invariant") with PKeywordLang with InvSpec + case object Invariant extends PKw("invariant") with PKeywordLang with InvSpec with LeftNewlineIndent type Invariant = PReserved[Invariant.type] case object Result extends PKw("result") with PKeywordLang with PKeywordAtom { @@ -262,9 +304,11 @@ object PKw { } /** Anything that is composed of /![a-zA-Z]/ characters. */ -trait PSymbol extends PReservedString { +trait PSymbol extends PReservedString with Reformattable { def symbol: String override def token = symbol + + override def reformat(ctx: ReformatterContext): Cont = text(symbol) } trait PSymbolLang extends PSymbol diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala new file mode 100644 index 000000000..ebeabe739 --- /dev/null +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -0,0 +1,172 @@ +package viper.silver.parser + +import fastparse.Parsed +import viper.silver.ast +import viper.silver.ast.pretty.FastPrettyPrinterBase +import viper.silver.ast.{HasLineColumn, LineColumnPosition, Position} +import viper.silver.parser.FastParserCompanion.programTrivia +import viper.silver.plugin.standard.adt.PAdtConstructor + +import scala.util.control.Breaks.{break, breakable} + +trait Reformattable extends FastPrettyPrinterBase { + def reformat(ctx: ReformatterContext): Cont +} + +trait ReformattableExpression extends FastPrettyPrinterBase { + def reformatExp(ctx: ReformatterContext): Cont +} + +class ReformatterContext(val program: String, val offsets: Seq[Int]) { + var currentOffset: Int = 0 + + def getByteOffset(p: HasLineColumn): Int = { + val row = offsets(p.line - 1); + row + p.column - 1 + } + + def getTrivia(pos: (ast.Position, ast.Position)): Seq[Trivia] = { + pos._1 match { + case p: HasLineColumn => { + val p_offset = getByteOffset(p); + getTriviaByByteOffset(p_offset) + } + case _ => Seq() + } + } + + def getTriviaByByteOffset(offset: Int): Seq[Trivia] = { + if (currentOffset <= offset) { + val str = program.substring(currentOffset, offset); + this.currentOffset = offset; + + fastparse.parse(str, programTrivia(_)) match { + case Parsed.Success(value, _) => { + println(s"Length: ${value.length}") + value + } + case _: Parsed.Failure => Seq() + } + } else { + Seq() + }; + } +} + +object ReformatPrettyPrinter extends FastPrettyPrinterBase { + override val defaultIndent = 4 + + def reformatProgram(p: PProgram): String = { + val ctx = new ReformatterContext(p.rawProgram, p.offsets); + super.pretty(defaultWidth, show(p, ctx)) + } + + def showOption[T <: Any](n: Option[T], ctx: ReformatterContext): Cont = { + n match { + case Some(r) => showAny(r, ctx) + case None => nil + } + } + + def showAnnotations(annotations: Seq[PAnnotation], ctx: ReformatterContext): Cont = { + if (annotations.isEmpty) { + nil + } else { + annotations.map(show(_, ctx)).foldLeft(nil)((acc, n) => acc <@@> n) + } + } + + def showReturns(returns: Option[PMethodReturns], ctx: ReformatterContext): Cont = { + returns.map(a => nil <+> show(a, ctx)).getOrElse(nil) + } + + def showPresPosts(pres: PDelimited[_, _], posts: PDelimited[_, _], ctx: ReformatterContext): Cont = { + nest(defaultIndent, (if (pres.isEmpty) nil + else line <> show(pres, ctx)) <> + (if (posts.isEmpty) nil + else line <> show(posts, ctx) + ) + ) + } + + def showInvs(invs: PDelimited[_, _], ctx: ReformatterContext): Cont = { + nest(defaultIndent, (if (invs.isEmpty) nil else line <> show(invs, ctx))) + } + + def showBody(body: Cont, newline: Boolean): Cont = { + if (newline) { + linebreak <> body + } else { + nil <+> body + } + } + + def formatTrivia(trivia: Seq[Trivia], ctx: ReformatterContext): Cont = { + trivia.filter({ + case _: PComment => true + case _ => false + }) + .foldLeft(nil)(_ <@@@> show(_, ctx)) + } + + def show(r: Reformattable, ctx: ReformatterContext): Cont = { + val trivia = r match { + case p: PLeaf => { + val trivia = ctx.getTrivia(p.pos); + val findNewlines = (trivia: Seq[Trivia]) => { + var count = 0; + breakable { + for (el <- trivia) { + el match { + case _: PComment => break + case _: PNewLine => count += 1 + case _ => + } + } + } + + if (count > 1) linebreak else nil + } + + val lw = findNewlines(trivia); + val tw = findNewlines(trivia.reverse); + val hasComment = trivia exists { + case _: PComment => true + case _ => false + } + + if (hasComment) { + lw <> formatTrivia(trivia, ctx) <> tw + } else { + lw + } + + }; + case _ => nil + } + + trivia <@@@> r.reformat(ctx) + } + + def showAny(n: Any, ctx: ReformatterContext): Cont = { + n match { + case p: Reformattable => show(p, ctx) + case p: Option[Any] => showOption(p, ctx) + case p: Seq[Any] => showSeq(p, ctx) + case p: Right[Any, Any] => showAny(p.value, ctx) + case p: Left[Any, Any] => showAny(p.value, ctx) + } + } + + def showSeq(l: Seq[Any], ctx: ReformatterContext): Cont = { + if (l.isEmpty) { + nil + } else { + val sep = l.head match { + case _: PAdtConstructor => linebreak + case _ => linebreak + } + l.map(showAny(_, ctx)).reduce(_ <> sep <> _) + } + } +} \ No newline at end of file diff --git a/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala b/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala index 71c0fc7cb..f6b8412fc 100644 --- a/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala +++ b/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala @@ -6,13 +6,12 @@ package viper.silver.plugin -import viper.silver.parser.{NameAnalyser, PAnnotationsPosition, PExp, PExtender, PKeyword, PSpecification, PKw, PMember, PReserved, PStmt, PTypeSubstitution, Translator, TypeChecker} +import viper.silver.parser.{NameAnalyser, PAnnotationsPosition, PExp, PExtender, PKeyword, PKw, PMember, PReserved, PSpecification, PStmt, PTypeSubstitution, ReformatterContext, Translator, TypeChecker} import viper.silver.ast.pretty.PrettyPrintPrimitives -import viper.silver.ast.{Declaration, ErrorTrafo, Exp, ExtensionExp, ExtensionMember, ExtensionStmt, Info, Member, Node, NoPosition, Position, Stmt, Type} +import viper.silver.ast.{Declaration, ErrorTrafo, Exp, ExtensionExp, ExtensionMember, ExtensionStmt, Info, Member, NoPosition, Node, Position, Stmt, Type} import viper.silver.verifier.VerificationResult import scala.collection.Set - import fastparse._ trait ParserPluginTemplate { @@ -95,6 +94,7 @@ trait ParserPluginTemplate { override def translateMember(t: Translator): Member = ??? override def translateMemberSignature(t: Translator): Member = super.translateMemberSignature(t) override def pretty = "" + override def reformat(ctx: ReformatterContext): Cont = "" } case class PExampleStmt()(val pos: (Position, Position)) extends PExtender with PStmt{ @@ -103,6 +103,7 @@ trait ParserPluginTemplate { // The overridden function to translate this node to a corresponding Ast node override def translateStmt(t: Translator): Stmt = super.translateStmt(t) + override def reformat(ctx: ReformatterContext): Cont = "" } case class PExampleExp()(val pos: (Position, Position)) extends PExtender with PExp{ @@ -114,6 +115,7 @@ trait ParserPluginTemplate { override def typecheck(t: TypeChecker, n: NameAnalyser): Option[Seq[String]] = super.typecheck(t, n) // The translator function to translate the PAst node corresponding to the Ast node override def translateExp(t: Translator): Exp = super.translateExp(t) + override def reformatExp(ctx: ReformatterContext): Cont = "" } /** diff --git a/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala index 4c9a0e870..06614448d 100644 --- a/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala @@ -13,6 +13,7 @@ import viper.silver.plugin.standard.adt.PAdtConstructor.findAdtConstructor import scala.annotation.unused import viper.silver.ast.utility.rewriter.HasExtraVars +import viper.silver.parser.ReformatPrettyPrinter.{show, showAnnotations, showOption} /** * Keywords used to define ADT's @@ -76,6 +77,9 @@ case class PAdt(annotations: Seq[PAnnotation], adt: PReserved[PAdtKeyword.type], adtType.kind = PAdtTypeKinds.Adt adtType } + + override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> show(adt, ctx) <+> + show(idndef, ctx) <> showOption(typVars, ctx) <+> show(c, ctx) } object PAdt { @@ -97,12 +101,19 @@ trait PAdtChild extends PNode { case class PAdtSeq[T <: PNode](seq: PGrouped[PSym.Brace, Seq[T]])(val pos: (Position, Position)) extends PExtender { def inner: Seq[T] = seq.inner override def pretty = s"${seq.l.pretty}\n ${seq.inner.map(_.pretty).mkString("\n ")}\n${seq.r.pretty}" + + override def reformat(ctx: ReformatterContext): Cont = { + show(seq, ctx) + } } /** Any argument to a method, function or predicate. */ case class PAdtFieldDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAnyFormalArgDecl with PTypedDeclaration with PGlobalDeclaration with PMemberUniqueDeclaration with PAdtChild { def constructor: PAdtConstructor = getAncestor[PAdtConstructor].get def annotations: Seq[PAnnotation] = Nil + + override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <> + show(c, ctx) <+> show(typ, ctx) } object PAdtFieldDecl { def apply(d: PIdnTypeBinding): PAdtFieldDecl = PAdtFieldDecl(d.idndef, d.c, d.typ)(d.pos) @@ -137,6 +148,9 @@ case class PAdtConstructor(annotations: Seq[PAnnotation], idndef: PIdnDef, args: override def keyword = adt.adt override def c = PReserved.implied(PSym.Colon) override def body = None + + override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> + show(idndef, ctx) <> show(args, ctx) } object PAdtConstructor { @@ -165,6 +179,8 @@ case class PAdtDeriving(k: PReserved[PDerivesKeyword.type], derivingInfos: PAdtS None } + + override def reformat(ctx: ReformatterContext): Cont = show(k, ctx) <+> show(derivingInfos, ctx) } case class PAdtWithout(k: PReserved[PWithoutKeyword.type], blockList: PDelimited[PIdnRef[PAdtFieldDecl], PSym.Comma])(val pos: (Position, Position)) extends PExtender with PPrettySubnodes with PAdtChild { @@ -177,6 +193,8 @@ case class PAdtWithout(k: PReserved[PWithoutKeyword.type], blockList: PDelimited }) None } + + override def reformat(ctx: ReformatterContext): Cont = show(k, ctx) <+> show(blockList, ctx) } case class PAdtDerivingInfo(idndef: PIdnDef, param: Option[PGrouped[PSym.Bracket, PType]], without: Option[PAdtWithout])(val pos: (Position, Position)) extends PExtender with PPrettySubnodes { @@ -186,6 +204,8 @@ case class PAdtDerivingInfo(idndef: PIdnDef, param: Option[PGrouped[PSym.Bracket without map (_.typecheck(t, n)) None } + + override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <+> showOption(param, ctx) } case class PAdtType(adt: PIdnRef[PAdt], args: Option[PDelimited.Comma[PSym.Bracket, PType]]) @@ -456,6 +476,9 @@ case class PConstructorCall(idnref: PIdnRef[PAdtConstructor], callArgs: PDelimit case _ => sys.error("type unification error - should report and not crash") } } + + override def reformatExp(ctx: ReformatterContext): Cont = show(idnref, ctx) <> + show(callArgs, ctx) <> showOption(typeAnnotated, ctx) } case class PDestructorCall(rcv: PExp, dot: PReserved[PDiscDot.type], idnref: PIdnRef[PAdtFieldDecl]) @@ -488,6 +511,8 @@ case class PDestructorCall(rcv: PExp, dot: PReserved[PDiscDot.type], idnref: PId case _ => sys.error("type unification error - should report and not crash") } } + + override def reformatExp(ctx: ReformatterContext): Cont = show(rcv, ctx) <> show(dot, ctx) <> show(idnref, ctx) } case object PIsKeyword extends PKwOp("is") { @@ -524,4 +549,6 @@ case class PDiscriminatorCall(rcv: PExp, dot: PReserved[PDiscDot.type], is: PRes case _ => sys.error("type unification error - should report and not crash") } } + + override def reformatExp(ctx: ReformatterContext): Cont = show(rcv, ctx) <> show(dot, ctx) <> show(is, ctx) <> show(idnref, ctx) } \ No newline at end of file diff --git a/src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePASTExtension.scala index 84c78ef27..bcf0c5c40 100644 --- a/src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePASTExtension.scala @@ -7,6 +7,7 @@ package viper.silver.plugin.standard.predicateinstance import viper.silver.ast._ +import viper.silver.parser.ReformatPrettyPrinter.show import viper.silver.parser._ import scala.collection.mutable @@ -43,4 +44,7 @@ case class PPredicateInstance(m: PReserved[PMarkerSymbol.type], idnuse: PIdnRef[ override def translateExp(t: Translator): ExtensionExp = { PredicateInstance(idnuse.name, args.inner.toSeq map t.exp)(t.liftPos(this)) } + + override def reformatExp(ctx: ReformatterContext): Cont = show(m, ctx) <> + show(idnuse, ctx) <> show(args, ctx) } diff --git a/src/main/scala/viper/silver/plugin/standard/refute/RefutePASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/refute/RefutePASTExtension.scala index 440f30a1f..fb6a258c4 100644 --- a/src/main/scala/viper/silver/plugin/standard/refute/RefutePASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/refute/RefutePASTExtension.scala @@ -7,6 +7,7 @@ package viper.silver.plugin.standard.refute import viper.silver.ast.{Position, Stmt} +import viper.silver.parser.ReformatPrettyPrinter.show import viper.silver.parser.TypeHelper.Bool import viper.silver.parser._ @@ -21,4 +22,6 @@ case class PRefute(refute: PReserved[PRefuteKeyword.type], e: PExp)(val pos: (Po } override def translateStmt(t: Translator): Stmt = Refute(t.exp(e))(t.liftPos(this)) + + override def reformat(ctx: ReformatterContext): Cont = show(refute, ctx) <+> show(e, ctx) } diff --git a/src/main/scala/viper/silver/plugin/standard/smoke/UnreachablePASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/smoke/UnreachablePASTExtension.scala index 6bc758224..96d760b42 100644 --- a/src/main/scala/viper/silver/plugin/standard/smoke/UnreachablePASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/smoke/UnreachablePASTExtension.scala @@ -7,6 +7,7 @@ package viper.silver.plugin.standard.smoke import viper.silver.ast.{Position, Stmt} +import viper.silver.parser.ReformatPrettyPrinter.show import viper.silver.parser._ /** Keyword used to define `unreachable` statement. */ @@ -18,4 +19,6 @@ case class PUnreachable(kw: PReserved[PUnreachableKeyword.type])(val pos: (Posit } override def translateStmt(t: Translator): Stmt = Unreachable()(t.liftPos(this)) + + override def reformat(ctx: ReformatterContext): Cont = show(kw, ctx) } diff --git a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala index 81ea1690b..e5b44cbf4 100644 --- a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala @@ -7,10 +7,11 @@ package viper.silver.plugin.standard.termination import viper.silver.ast._ +import viper.silver.parser.ReformatPrettyPrinter.{show, showOption} import viper.silver.parser.TypeHelper.Bool import viper.silver.parser._ -case object PDecreasesKeyword extends PKw("decreases") with PKeywordLang with PKw.AnySpec +case object PDecreasesKeyword extends PKw("decreases") with PKeywordLang with PKw.AnySpec with LeftNewlineIndent case object PIfKeyword extends PKw("if") with PKeywordLang case object PWildcardSym extends PSym("_") with PSymbolLang @@ -42,6 +43,9 @@ case class PDecreasesTuple(tuple: PDelimited[PExp, PSym.Comma], condition: Optio override def translateExp(t: Translator): ExtensionExp = { DecreasesTuple(tuple.toSeq map t.exp, condition map (_._2) map t.exp)(t.liftPos(this)) } + + override def reformatExp(ctx: ReformatterContext): Cont = + show(tuple, ctx) <> condition.map((e) => space <> show(e._1, ctx) <+> show(e._2, ctx)).getOrElse(nil) } case class PDecreasesWildcard(wildcard: PReserved[PWildcardSym.type], condition: Option[(PReserved[PIfKeyword.type], PExp)] = None)(val pos: (Position, Position)) extends PDecreasesClause { @@ -55,6 +59,9 @@ case class PDecreasesWildcard(wildcard: PReserved[PWildcardSym.type], condition: override def translateExp(t: Translator): ExtensionExp = { DecreasesWildcard(condition map (_._2) map t.exp)(t.liftPos(this)) } + + override def reformatExp(ctx: ReformatterContext): Cont = show(wildcard, ctx) <+> + condition.map((e) => show(e._1, ctx) <+> show(e._2, ctx)).getOrElse(nil) } case class PDecreasesStar(star: PSym.Star)(val pos: (Position, Position)) extends PDecreasesClause { @@ -66,5 +73,7 @@ case class PDecreasesStar(star: PSym.Star)(val pos: (Position, Position)) extend override def translateExp(t: Translator): ExtensionExp = { DecreasesStar()(t.liftPos(this)) } + + override def reformatExp(ctx: ReformatterContext): Cont = show(star, ctx) } diff --git a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPlugin.scala b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPlugin.scala index a77b9ff91..cc20f32b3 100644 --- a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPlugin.scala +++ b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPlugin.scala @@ -194,7 +194,7 @@ class TerminationPlugin(@unused reporter: viper.silver.reporter.Reporter, val importOnlyProgram = importStmts.mkString("\n") val importPProgram = PAstProvider.generateViperPAst(importOnlyProgram).get.filterMembers(_.isInstanceOf[PDomain]) val inputFiltered = input.filterMembers(m => !(m.isInstanceOf[PDomain] && m.asInstanceOf[PDomain].idndef.name == "WellFoundedOrder")) - val mergedProgram = PProgram(inputFiltered.imported :+ importPProgram, inputFiltered.members)(input.pos, input.localErrors) + val mergedProgram = PProgram(inputFiltered.imported :+ importPProgram, inputFiltered.members)(input.pos, input.localErrors, input.offsets, input.rawProgram) super.beforeTranslate(mergedProgram) } else { super.beforeTranslate(input) diff --git a/src/test/scala/ASTTransformationTests.scala b/src/test/scala/ASTTransformationTests.scala index d3a6ec517..509e3bcf5 100644 --- a/src/test/scala/ASTTransformationTests.scala +++ b/src/test/scala/ASTTransformationTests.scala @@ -84,11 +84,11 @@ class ASTTransformationTests extends AnyFunSuite { val p = (NoPosition, NoPosition) val binExp1 = PBinExp(PIntLit(1)(p), PReserved.implied(PSymOp.EqEq), PIntLit(1)(p))(p) val method1 = PMethod(Seq(), PReserved.implied(PKw.Method), PIdnDef("m")(p), PGrouped.impliedParen(PDelimited.empty), None, PDelimited.empty, PDelimited.empty, Some(PSeqn(PDelimited.impliedBlock(Seq(PAssert(PReserved.implied(PKw.Assert), binExp1)(p))))(p)))(p) - val original = PProgram(Nil, Seq(method1))(p, Seq()) + val original = PProgram(Nil, Seq(method1))(p, Seq(), Seq(),"") val binExp2 = PBinExp(PIntLit(3)(p), PReserved.implied(PSymOp.EqEq), PIntLit(3)(p))(p) val method2 = PMethod(Seq(), PReserved.implied(PKw.Method), PIdnDef("m")(p), PGrouped.impliedParen(PDelimited.empty), None, PDelimited.empty, PDelimited.empty, Some(PSeqn(PDelimited.impliedBlock(Seq(PAssert(PReserved.implied(PKw.Assert), binExp2)(p))))(p)))(p) - val target = PProgram(Nil, Seq(method2))(p, Seq()) + val target = PProgram(Nil, Seq(method2))(p, Seq(), Seq(),"") case class Context(increment: Int) @@ -124,11 +124,11 @@ class ASTTransformationTests extends AnyFunSuite { val function = PFunction(Seq(), PReserved.implied(PKw.Function), PIdnDef("f")(p), commaParen(Seq(PFormalArgDecl(PIdnDef("x")(p), PReserved.implied(PSym.Colon), TypeHelper.Int)(p), PFormalArgDecl(PIdnDef("y")(p), PReserved.implied(PSym.Colon), TypeHelper.Int)(p))), PReserved.implied(PSym.Colon), TypeHelper.Int, PDelimited.empty, PDelimited.empty, None)(p) val assume1 = PAssume(PReserved.implied(PKw.Assume), PBinExp(PCall(PIdnRef("f")(p), commaParen(Seq(PIntLit(1)(p), PIntLit(1)(p))), None)(p), PReserved.implied(PSymOp.EqEq), PCall(PIdnRef("f")(p), commaParen(Seq(PIntLit(1)(p), PCall(PIdnRef("f")(p), commaParen(Seq(PIntLit(1)(p), PCall(PIdnRef("f")(p), commaParen(Seq(PIntLit(1)(p), PIntLit(1)(p))), None)(p))), None)(p))), None)(p))(p))(p) val method1 = PMethod(Seq(), PReserved.implied(PKw.Method), PIdnDef("m")(p), PGrouped.impliedParen(PDelimited.empty), None, PDelimited.empty, PDelimited.empty, Some(PSeqn(PDelimited.impliedBlock(Seq(assume1)))(p)))(p) - val original = PProgram(Nil, Seq(function, method1))(p, Seq()) + val original = PProgram(Nil, Seq(function, method1))(p, Seq(), Seq(),"") val assume2 = PAssume(PReserved.implied(PKw.Assume), PBinExp(PCall(PIdnRef("f")(p), commaParen(Seq(PIntLit(2)(p), PIntLit(1)(p))), None)(p), PReserved.implied(PSymOp.EqEq), PCall(PIdnRef("f")(p), commaParen(Seq(PIntLit(2)(p), PCall(PIdnRef("f")(p), commaParen(Seq(PIntLit(3)(p), PCall(PIdnRef("f")(p), commaParen(Seq(PIntLit(4)(p), PIntLit(1)(p))), None)(p))), None)(p))), None)(p))(p))(p) val method2 = PMethod(Seq(), PReserved.implied(PKw.Method), PIdnDef("m")(p), PGrouped.impliedParen(PDelimited.empty), None, PDelimited.empty, PDelimited.empty, Some(PSeqn(PDelimited.impliedBlock(Seq(assume2)))(p)))(p) - val target = PProgram(Nil, Seq(function, method2))(p, Seq()) + val target = PProgram(Nil, Seq(function, method2))(p, Seq(), Seq(),"") case class Context(increment: Int) @@ -149,7 +149,7 @@ class ASTTransformationTests extends AnyFunSuite { val p = (NoPosition, NoPosition) val requires = PForall(PReserved.implied(PKw.Forall), PDelimited.implied(Seq(PLogicalVarDecl(PIdnDef("y")(p), PReserved.implied(PSym.Colon), TypeHelper.Int)(p)), PReserved.implied(PSym.Comma)), PReserved.implied(PSym.ColonColon), Seq(), PBinExp(PIdnUseExp("y")(p), PReserved.implied(PSymOp.EqEq), PIdnUseExp("y")(p))(p))(p) val function = PFunction(Seq(), PReserved.implied(PKw.Function), PIdnDef("f")(p), PDelimited.impliedParenComma(Seq(PFormalArgDecl(PIdnDef("x")(p), PReserved.implied(PSym.Colon), TypeHelper.Ref)(p))), PReserved.implied(PSym.Colon), TypeHelper.Bool, PDelimited.implied(Seq(PSpecification(PReserved.implied(PKw.Requires), requires)(p)), None), PDelimited.empty, None)(p) - val program = PProgram(Nil, Seq(function))(p, Seq()) + val program = PProgram(Nil, Seq(function))(p, Seq(), Seq(),"") case class Context() diff --git a/src/test/scala/PluginTests.scala b/src/test/scala/PluginTests.scala index 1f34f2ef3..dfafef508 100644 --- a/src/test/scala/PluginTests.scala +++ b/src/test/scala/PluginTests.scala @@ -121,7 +121,7 @@ class TestPluginAddPredicate extends SilverPlugin { PProgram( input.imported, input.members :+ PPredicate(Seq(), PReserved.implied(PKw.Predicate), PIdnDef("testPredicate")(p), PGrouped.impliedParen(PDelimited.empty), None)(p), - )(input.pos, input.localErrors) + )(input.pos, input.localErrors, input.offsets, input.rawProgram) } /** Called after methods are filtered but before the verification by the backend happens. diff --git a/src/test/scala/SemanticAnalysisTests.scala b/src/test/scala/SemanticAnalysisTests.scala index 2d9ace8e5..7a9b0919c 100644 --- a/src/test/scala/SemanticAnalysisTests.scala +++ b/src/test/scala/SemanticAnalysisTests.scala @@ -31,7 +31,7 @@ class SemanticAnalysisTests extends AnyFunSuite { val binExp2 = PBinExp(PIntLit(1)(p), PReserved.implied(PSymOp.EqEq), PIntLit(1)(p))(p) val body = PSeqn(PDelimited.impliedBlock(Seq(PAssert(PReserved.implied(PKw.Assert), binExp1)(p), PSeqn(PDelimited.impliedBlock(Seq(PAssert(PReserved.implied(PKw.Assert), binExp2)(p))))(p))))(p) val method = PMethod(Seq(), PReserved.implied(PKw.Method), PIdnDef("m")(p), PGrouped.impliedParen(PDelimited.empty), None, PDelimited.empty, PDelimited.empty, Some(body))(p) - val program = PProgram(Nil, Seq(method))(p, Seq()) + val program = PProgram(Nil, Seq(method))(p, Seq(), Seq(),"") assert(frontend.doSemanticAnalysis(program) === frontend.Succ(program)) } @@ -40,7 +40,7 @@ class SemanticAnalysisTests extends AnyFunSuite { val binExp = PBinExp(PIntLit(1)(p), PReserved.implied(PSymOp.EqEq), PIntLit(1)(p))(p) val body = PSeqn(PDelimited.impliedBlock(Seq(PAssert(PReserved.implied(PKw.Assert), binExp)(p), PSeqn(PDelimited.impliedBlock(Seq(PAssert(PReserved.implied(PKw.Assert), binExp)(p))))(p))))(p) val method = PMethod(Seq(), PReserved.implied(PKw.Method), PIdnDef("m")(p), PGrouped.impliedParen(PDelimited.empty), None, PDelimited.empty, PDelimited.empty, Some(body))(p) - val program = PProgram(Nil, Seq(method))(p, Seq()) + val program = PProgram(Nil, Seq(method))(p, Seq(), Seq(),"") assert(frontend.doSemanticAnalysis(program) === frontend.Succ(program)) } } From 18fa38e22a584945b100014d93921d67bf14565d Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Sat, 16 Nov 2024 19:39:24 +0100 Subject: [PATCH 02/47] Don't translate macros when reformatting --- src/main/scala/viper/silver/cfg/CfgTest.scala | 2 +- .../frontend/ReformatterAstProvider.scala | 21 +++++++++++++++++++ .../viper/silver/frontend/SilFrontend.scala | 6 ++++-- .../viper/silver/parser/FastParser.scala | 8 +++++-- 4 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 src/main/scala/viper/silver/frontend/ReformatterAstProvider.scala diff --git a/src/main/scala/viper/silver/cfg/CfgTest.scala b/src/main/scala/viper/silver/cfg/CfgTest.scala index 6000943d3..8500018c9 100644 --- a/src/main/scala/viper/silver/cfg/CfgTest.scala +++ b/src/main/scala/viper/silver/cfg/CfgTest.scala @@ -35,7 +35,7 @@ object CfgTest { } private def parse(input: String, file: Path): Option[PProgram] = { - val program = new FastParser().parse(input, file) + val program = new FastParser().parse(input, file, false) if (program.errors.forall(_.isInstanceOf[ParseWarning])) Some(program) else None } diff --git a/src/main/scala/viper/silver/frontend/ReformatterAstProvider.scala b/src/main/scala/viper/silver/frontend/ReformatterAstProvider.scala new file mode 100644 index 000000000..75102b82d --- /dev/null +++ b/src/main/scala/viper/silver/frontend/ReformatterAstProvider.scala @@ -0,0 +1,21 @@ +package viper.silver.frontend +import viper.silver.parser.PProgram +import viper.silver.reporter.Reporter +import viper.silver.verifier.{Failure, Success, VerificationResult} + +class ReformatterAstProvider(override val reporter: Reporter) extends ViperAstProvider(reporter) { + override val phases: Seq[Phase] = Seq(Parsing) + + override def doParsing(input: String): Result[PProgram] = parsingInner(input, false) + + override def result: VerificationResult = { + + if (_errors.isEmpty) { + require(state >= DefaultStates.Parsing) + Success + } + else { + Failure(_errors) + } + } +} diff --git a/src/main/scala/viper/silver/frontend/SilFrontend.scala b/src/main/scala/viper/silver/frontend/SilFrontend.scala index caf49316f..3f01122ce 100644 --- a/src/main/scala/viper/silver/frontend/SilFrontend.scala +++ b/src/main/scala/viper/silver/frontend/SilFrontend.scala @@ -310,11 +310,11 @@ trait SilFrontend extends DefaultFrontend { _config = configureVerifier(args) } - override def doParsing(input: String): Result[PProgram] = { + def parsingInner(input: String, expandMacros: Boolean): Result[PProgram] = { val file = _inputFile.get plugins.beforeParse(input, isImported = false) match { case Some(inputPlugin) => - val result = fp.parse(inputPlugin, file, Some(plugins), _loader) + val result = fp.parse(inputPlugin, file, expandMacros, Some(plugins), _loader) if (result.errors.forall(p => p.isInstanceOf[ParseWarning])) { reporter report WarningsDuringParsing(result.errors) Succ({ @@ -327,6 +327,8 @@ trait SilFrontend extends DefaultFrontend { } } + override def doParsing(input: String): Result[PProgram] = parsingInner(input, true) + override def doSemanticAnalysis(input: PProgram): Result[PProgram] = { plugins.beforeResolve(input) match { case Some(inputPlugin) => diff --git a/src/main/scala/viper/silver/parser/FastParser.scala b/src/main/scala/viper/silver/parser/FastParser.scala index a9cd7ab69..fcdbb8158 100644 --- a/src/main/scala/viper/silver/parser/FastParser.scala +++ b/src/main/scala/viper/silver/parser/FastParser.scala @@ -186,7 +186,7 @@ object FastParserCompanion { } class FastParser { - def parse(s: String, f: Path, plugins: Option[SilverPluginManager] = None, loader: FileLoader = DiskLoader) = { + def parse(s: String, f: Path, expandMacros: Boolean, plugins: Option[SilverPluginManager] = None, loader: FileLoader = DiskLoader) = { // Strategy to handle imports // Idea: Import every import reference and merge imported methods, functions, imports, .. into current program // iterate until no new imports are present. @@ -198,7 +198,11 @@ class FastParser { val file = f.toAbsolutePath().normalize() val data = ParserData(plugins, loader, mutable.HashSet(file)) val program = RecParser(file, data, false).parses(s) - MacroExpander.expandDefines(program) + if (expandMacros) { + MacroExpander.expandDefines(program) + } else { + program + } } case class ParserData(plugins: Option[SilverPluginManager], loader: FileLoader, local: mutable.HashSet[Path], std: mutable.HashSet[Path] = mutable.HashSet.empty) From e3555bfe7ba97937a0a974522bdd4b2df0068dab Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Sun, 17 Nov 2024 10:52:53 +0100 Subject: [PATCH 03/47] Refine expressions further --- src/main/scala/viper/silver/parser/ParseAst.scala | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 3b3345ae6..c972f5a8d 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -15,7 +15,7 @@ import java.util.concurrent.atomic.{AtomicInteger, AtomicLong} import viper.silver.ast.utility.Visitor import viper.silver.ast.utility.rewriter.{HasExtraValList, HasExtraVars, Rewritable, StrategyBuilder} import viper.silver.ast.{Exp, Member, NoPosition, SourcePosition, Stmt, Type} -import viper.silver.parser.PSymOp.{Iff, Implies} +import viper.silver.parser.PSymOp.{EqEq, Iff, Implies} import viper.silver.parser.TypeHelper._ import viper.silver.verifier.ParseReport @@ -1065,7 +1065,8 @@ class PBinExp(val left: PExp, val op: PReserved[PBinaryOp], val right: PExp)(val override def reformatExp(ctx: ReformatterContext): Cont = { op.rs match { - case Iff | Implies => + // Those two operators look a bit better if they stick on the previous line + case Iff | Implies | EqEq => group(show(left, ctx) <+> show(op, ctx) <> nest(defaultIndent, line <> show(right, ctx))) case _ => group(show(left, ctx) <@> show(op, ctx) <+> show(right, ctx)) } @@ -1216,8 +1217,8 @@ sealed trait PQuantifier extends PBinder { } case class PExists(keyword: PKw.Exists, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier { - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> - show(vars, ctx) <+> show(c, ctx) <+> showSeq(triggers, ctx) <+> show(body, ctx) + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> show(vars, ctx) <+> + show(c, ctx) <> nest(defaultIndent, group(line <> (showSeq(triggers, ctx) <+@> show(body, ctx)))) } case class PForall(keyword: PKw.Forall, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier { @@ -1228,7 +1229,9 @@ case class PForall(keyword: PKw.Forall, vars: PDelimited[PLogicalVarDecl, PSym.C case class PForPerm(keyword: PKw.Forperm, vars: PDelimited[PLogicalVarDecl, PSym.Comma], accessRes: PGrouped[PSym.Bracket, PResourceAccess], c: PSym.ColonColon, body: PExp)(val pos: (Position, Position)) extends PQuantifier { val triggers: Seq[PTrigger] = Seq() - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> show(vars, ctx) <+> show(accessRes, ctx) <+> show(c, ctx) <+> show(body, ctx) + override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> + show(vars, ctx) <+> show(accessRes, ctx) <+> show(c, ctx) <> + nest(defaultIndent, group(line <> show(body, ctx))) } /* Let-expressions `let x == e1 in e2` are represented by the nested structure From b2e869070ae7c5e4493ee72423585c0be8f372f7 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Sun, 17 Nov 2024 11:05:08 +0100 Subject: [PATCH 04/47] Update comment --- src/main/scala/viper/silver/parser/ParseAst.scala | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index c972f5a8d..ce6506c78 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -1065,7 +1065,7 @@ class PBinExp(val left: PExp, val op: PReserved[PBinaryOp], val right: PExp)(val override def reformatExp(ctx: ReformatterContext): Cont = { op.rs match { - // Those two operators look a bit better if they stick on the previous line + // Those operators look a bit better if they stick on the previous line case Iff | Implies | EqEq => group(show(left, ctx) <+> show(op, ctx) <> nest(defaultIndent, line <> show(right, ctx))) case _ => group(show(left, ctx) <@> show(op, ctx) <+> show(right, ctx)) @@ -1256,7 +1256,7 @@ case class PLet(l: PKwOp.Let, variable: PIdnDef, eq: PSymOp.EqEq, exp: PGrouped. } override def reformatExp(ctx: ReformatterContext): Cont = show(l, ctx) <+> show(variable, ctx) <+> - show(eq, ctx) <+> nest(defaultIndent, show(exp, ctx) <+> show(in, ctx) <@> show(nestedScope, ctx)) + show(eq, ctx) <> nest(defaultIndent, group(line <> show(exp, ctx) <+> show(in, ctx) <+> show(nestedScope, ctx))) } case class PLetNestedScope(body: PExp)(val pos: (Position, Position)) extends PTypedVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { @@ -1341,7 +1341,7 @@ case class PAccPred(op: PKwOp.Acc, amount: PGrouped.Paren[PMaybePairArgument[PLo def perm = amount.inner.second.map(_._2).getOrElse(PFullPerm.implied()) override val args = Seq(loc, perm) - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(amount, ctx) + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <+> show(amount, ctx) } case class POldExp(op: PKwOp.Old, label: Option[PGrouped[PSym.Bracket, Either[PKw.Lhs, PIdnRef[PLabel]]]], e: PGrouped.Paren[PExp])(val pos: (Position, Position)) extends PCallKeyword with PHeapOpApp { @@ -1349,7 +1349,7 @@ case class POldExp(op: PKwOp.Old, label: Option[PGrouped[PSym.Bracket, Either[PK override def requirePure = args override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pResS -> POpApp.pArg(0))) - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> showOption(label, ctx) <> show(e, ctx) + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <+> showOption(label, ctx) <+@> show(e, ctx) } case class PDebugLabelledOldExp(op: PKwOp.Old, label: PVersionedIdnUseExp, e: PExp)(val pos: (Position, Position)) extends PCallKeyword with PHeapOpApp { @@ -1359,7 +1359,7 @@ case class PDebugLabelledOldExp(op: PKwOp.Old, label: PVersionedIdnUseExp, e: PE override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pResS -> POpApp.pArg(0))) - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(label, ctx) <> show(e, ctx) + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <+> show(label, ctx) <+> show(e, ctx) } sealed trait PCollectionLiteral extends PCallKeyword { @@ -1407,11 +1407,11 @@ sealed trait PSeqLiteral extends PCollectionLiteral { } case class PEmptySeq(op: PKwOp.Seq, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PSeqLiteral with PEmptyCollectionLiteral { - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <+> showOption(pAnnotatedType, ctx) <> show(callArgs, ctx) + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> showOption(pAnnotatedType, ctx) <> show(callArgs, ctx) } case class PExplicitSeq(op: PKwOp.Seq, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PSeqLiteral with PExplicitCollectionLiteral { - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <+> show(callArgs, ctx) + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(callArgs, ctx) } // [low..high) From 6631424206e3e2879add872fa7e77d93d37da3d3 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Sun, 17 Nov 2024 11:11:40 +0100 Subject: [PATCH 05/47] Fix spacing --- src/main/scala/viper/silver/parser/ParseAst.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index ce6506c78..7507985a4 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -1341,7 +1341,7 @@ case class PAccPred(op: PKwOp.Acc, amount: PGrouped.Paren[PMaybePairArgument[PLo def perm = amount.inner.second.map(_._2).getOrElse(PFullPerm.implied()) override val args = Seq(loc, perm) - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <+> show(amount, ctx) + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(amount, ctx) } case class POldExp(op: PKwOp.Old, label: Option[PGrouped[PSym.Bracket, Either[PKw.Lhs, PIdnRef[PLabel]]]], e: PGrouped.Paren[PExp])(val pos: (Position, Position)) extends PCallKeyword with PHeapOpApp { @@ -1349,7 +1349,7 @@ case class POldExp(op: PKwOp.Old, label: Option[PGrouped[PSym.Bracket, Either[PK override def requirePure = args override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pResS -> POpApp.pArg(0))) - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <+> showOption(label, ctx) <+@> show(e, ctx) + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> showOption(label, ctx) <> show(e, ctx) } case class PDebugLabelledOldExp(op: PKwOp.Old, label: PVersionedIdnUseExp, e: PExp)(val pos: (Position, Position)) extends PCallKeyword with PHeapOpApp { @@ -1359,7 +1359,7 @@ case class PDebugLabelledOldExp(op: PKwOp.Old, label: PVersionedIdnUseExp, e: PE override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pResS -> POpApp.pArg(0))) - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <+> show(label, ctx) <+> show(e, ctx) + override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(label, ctx) <> show(e, ctx) } sealed trait PCollectionLiteral extends PCallKeyword { From dfd76247719018f6294674090b8d766bcb76371b Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Mon, 18 Nov 2024 10:36:36 +0100 Subject: [PATCH 06/47] Change PForAll --- src/main/scala/viper/silver/parser/ParseAst.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 7507985a4..f353615cb 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -1223,7 +1223,7 @@ case class PExists(keyword: PKw.Exists, vars: PDelimited[PLogicalVarDecl, PSym.C case class PForall(keyword: PKw.Forall, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier { override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> show(vars, ctx) <+> - show(c, ctx) <> nest(defaultIndent, group(line <> (showSeq(triggers, ctx) <+@> show(body, ctx)))) + show(c, ctx) <> nest(defaultIndent, group(line <> group(showSeq(triggers, ctx) <+@> show(body, ctx)))) } case class PForPerm(keyword: PKw.Forperm, vars: PDelimited[PLogicalVarDecl, PSym.Comma], accessRes: PGrouped[PSym.Bracket, PResourceAccess], c: PSym.ColonColon, body: PExp)(val pos: (Position, Position)) extends PQuantifier { @@ -2107,8 +2107,8 @@ case class PNewLine() extends Trivia { case class PComment(content: String, block: Boolean) extends Trivia { override def reformat(ctx: ReformatterContext): Cont = if (block) { - text("/*") <> content <> text("*/") <> linebreak + text("/*") <> content <> text("*/") } else { - text("//") <> text(content) <> linebreak + text("//") <> text(content) } } \ No newline at end of file From abd6f491d4e949e99364a3dbd75c84673e5d4ba7 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Mon, 18 Nov 2024 12:27:26 +0100 Subject: [PATCH 07/47] more --- src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala | 3 +++ src/main/scala/viper/silver/parser/ParseAst.scala | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala index 92c88c12e..85d22e881 100644 --- a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala +++ b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala @@ -359,6 +359,9 @@ trait FastPrettyPrinterBase extends PrettyPrintPrimitives { def linebreak : Cont = line ("\n") + def dlinebreak : Cont = + line ("\n\n") + implicit class ContOps(dl: Cont) { def <>(dr: Cont) : Cont = diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index f353615cb..065fddeca 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -2107,8 +2107,8 @@ case class PNewLine() extends Trivia { case class PComment(content: String, block: Boolean) extends Trivia { override def reformat(ctx: ReformatterContext): Cont = if (block) { - text("/*") <> content <> text("*/") + text("/*") <> content <> text("*/") <> linebreak } else { - text("//") <> text(content) + text("//") <> text(content) <> linebreak } } \ No newline at end of file From b187fee15367f3d8d824299b77f8a09eb18393dd Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Tue, 19 Nov 2024 09:55:49 +0100 Subject: [PATCH 08/47] Tweak formatting of let and if statements --- src/main/scala/viper/silver/parser/ParseAst.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 065fddeca..e98a8a529 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -1098,7 +1098,7 @@ case class PCondExp(cond: PExp, q: PSymOp.Question, thn: PExp, c: PSymOp.Colon, override def reformatExp(ctx: ReformatterContext): Cont = show(cond, ctx) <+> show(q, ctx) <> nest(defaultIndent, group(line <> show(thn, ctx) <+> - show(c, ctx) <> nest(defaultIndent, group(line <> show(els, ctx))))) + show(c, ctx) <> group(line <> show(els, ctx)))) } // Simple literals @@ -1256,7 +1256,7 @@ case class PLet(l: PKwOp.Let, variable: PIdnDef, eq: PSymOp.EqEq, exp: PGrouped. } override def reformatExp(ctx: ReformatterContext): Cont = show(l, ctx) <+> show(variable, ctx) <+> - show(eq, ctx) <> nest(defaultIndent, group(line <> show(exp, ctx) <+> show(in, ctx) <+> show(nestedScope, ctx))) + show(eq, ctx) <+> show(exp, ctx) <+> show(in, ctx) <> group(line <> show(nestedScope, ctx)) } case class PLetNestedScope(body: PExp)(val pos: (Position, Position)) extends PTypedVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { @@ -1675,7 +1675,7 @@ case class PAssign(targets: PDelimited[PExp with PAssignTarget, PSym.Comma], op: sealed trait PIfContinuation extends PStmt case class PIf(keyword: PReserved[PKeywordIf], cond: PGrouped.Paren[PExp], thn: PSeqn, els: Option[PIfContinuation])(val pos: (Position, Position)) extends PStmt with PIfContinuation { override def reformat(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> show(cond, ctx) <> - showBody(show(thn, ctx), true) <+@> showBody(showOption(els, ctx), false) + showBody(show(thn, ctx), false) <+@> showBody(showOption(els, ctx), false) } case class PElse(k: PKw.Else, els: PSeqn)(val pos: (Position, Position)) extends PStmt with PIfContinuation { @@ -2011,7 +2011,7 @@ case class PFunction(annotations: Seq[PAnnotation], keyword: PKw.Function, idnde println(s"---------------------------"); println(s"body ${body}"); showAnnotations(annotations, ctx) <@@> show(keyword, ctx) <+> show(idndef, ctx) <> - show(args, ctx) <+> show(c, ctx) <+> show(resultType, ctx) <> + show(args, ctx) <> show(c, ctx) <+> show(resultType, ctx) <> showPresPosts(pres, posts, ctx) <> showBody(showOption(body, ctx), !(pres.isEmpty && posts.isEmpty)) } } From b90d0a6e48b1d4899827afe013993b09b89bdf03 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Tue, 19 Nov 2024 11:21:49 +0100 Subject: [PATCH 09/47] First version of better trivia fetching --- .../scala/viper/silver/parser/ParseAst.scala | 16 ++++-- .../silver/parser/ReformatPrettyPrinter.scala | 53 +++++++++++++------ .../standard/adt/AdtPASTExtension.scala | 2 + 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index e98a8a529..fdb25f589 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -479,6 +479,8 @@ case class PDomainType(domain: PIdnRef[PTypeDeclaration], args: Option[PDelimite if (s.length == 0 && args.isEmpty) this else copy(args = Some(args.get.update(s)))(pos) override def copyExtraVars(from: Any): Unit = this.kind = from.asInstanceOf[PDomainType].kind + + override def reformat(ctx: ReformatterContext): Cont = show(domain, ctx) <> showOption(args, ctx) } object PDomainTypeKinds { @@ -553,8 +555,6 @@ trait PGenericType extends PType { val argsPretty = if (typeArguments.isEmpty) "" else typeArguments.map(_.pretty).mkString("[", ", ", "]") s"$genericName$argsPretty" } - - override def reformat(ctx: ReformatterContext): Cont = text(pretty) } sealed trait PGenericCollectionType extends PGenericType { @@ -573,16 +573,22 @@ sealed trait PGenericCollectionType extends PGenericType { case class PSeqType(seq: PKw.Seq, elementType: PGrouped[PSym.Bracket, PType])(val pos: (Position, Position)) extends PType with PGenericCollectionType { override val genericName = "Seq" override def update(newType: PType) = copy(elementType = elementType.update(newType))(pos) + + override def reformat(ctx: ReformatterContext): Cont = show(seq, ctx) <> show(elementType, ctx) } case class PSetType(set: PKw.Set, elementType: PGrouped[PSym.Bracket, PType])(val pos: (Position, Position)) extends PType with PGenericCollectionType { override val genericName = "Set" override def update(newType: PType) = copy(elementType = elementType.update(newType))(pos) + + override def reformat(ctx: ReformatterContext): Cont = show(set, ctx) <> show(elementType, ctx) } case class PMultisetType(multiset: PKw.Multiset, elementType: PGrouped[PSym.Bracket, PType])(val pos: (Position, Position)) extends PType with PGenericCollectionType { override val genericName = "Multiset" override def update(newType: PType) = copy(elementType = elementType.update(newType))(pos) + + override def reformat(ctx: ReformatterContext): Cont = show(multiset, ctx) <> show(elementType, ctx) } case class PMapType(map: PKw.Map, typ: PGrouped[PSym.Bracket, PPairArgument[PType, PType]])(val pos: (Position, Position)) extends PType with PGenericType { @@ -599,6 +605,8 @@ case class PMapType(map: PKw.Map, typ: PGrouped[PSym.Bracket, PPairArgument[PTyp override def withTypeArguments(s: Seq[PType]): PMapType = copy(typ = typ.update(PPairArgument(s(0), typ.inner.c, s(1))(typ.inner.pos)))(pos) + + override def reformat(ctx: ReformatterContext): Cont = show(map, ctx) <> show(typ, ctx) } /** Exists temporarily after parsing and is replaced with @@ -1875,9 +1883,9 @@ case class PProgram(imported: Seq[PProgram], members: Seq[PMember])(val pos: (Po override def reformat(ctx: ReformatterContext): Cont = { println(s"whole program ${this.members}"); - members.map(show(_, ctx)).foldLeft(nil)((acc, n) => acc <@@> n) <> + members.map(show(_, ctx)).foldLeft(nil)((acc, n) => acc <@@> n) // Don't forget comments that appear after any nodes! - formatTrivia(ctx.getTriviaByByteOffset(rawProgram.length), ctx) +// formatTrivia(ctx.getTriviaByByteOffset(rawProgram.length), ctx) } // Pretty print members in a specific order diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index ebeabe739..d36c0433b 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -7,6 +7,7 @@ import viper.silver.ast.{HasLineColumn, LineColumnPosition, Position} import viper.silver.parser.FastParserCompanion.programTrivia import viper.silver.plugin.standard.adt.PAdtConstructor +import scala.:: import scala.util.control.Breaks.{break, breakable} trait Reformattable extends FastPrettyPrinterBase { @@ -17,32 +18,29 @@ trait ReformattableExpression extends FastPrettyPrinterBase { def reformatExp(ctx: ReformatterContext): Cont } -class ReformatterContext(val program: String, val offsets: Seq[Int]) { - var currentOffset: Int = 0 - +class ReformatterContext(val program: String, val offsets: Seq[Int], val posMap: Map[Position, Position]) { def getByteOffset(p: HasLineColumn): Int = { val row = offsets(p.line - 1); row + p.column - 1 } - def getTrivia(pos: (ast.Position, ast.Position)): Seq[Trivia] = { - pos._1 match { - case p: HasLineColumn => { + def getTrivia(start: ast.Position, end: ast.Position): Seq[Trivia] = { + (start, end) match { + case (p: HasLineColumn, q: HasLineColumn) => { val p_offset = getByteOffset(p); - getTriviaByByteOffset(p_offset) + val q_offset = getByteOffset(q); + getTriviaByByteOffset(p_offset, q_offset) } case _ => Seq() } } - def getTriviaByByteOffset(offset: Int): Seq[Trivia] = { - if (currentOffset <= offset) { - val str = program.substring(currentOffset, offset); - this.currentOffset = offset; + def getTriviaByByteOffset(startOffset: Int, endOffset: Int): Seq[Trivia] = { + if (startOffset < endOffset) { + val str = program.substring(startOffset, endOffset); fastparse.parse(str, programTrivia(_)) match { case Parsed.Success(value, _) => { - println(s"Length: ${value.length}") value } case _: Parsed.Failure => Seq() @@ -57,7 +55,22 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { override val defaultIndent = 4 def reformatProgram(p: PProgram): String = { - val ctx = new ReformatterContext(p.rawProgram, p.offsets); + def collectLeavePositions(p: PNode): Seq[(ast.Position, ast.Position)] = { + p match { + case p: PLeaf => Seq(p.pos) + case _ => p.subnodes.flatMap(collectLeavePositions) + } + } + val leavePositions = collectLeavePositions(p) + var positions: Map[ast.Position, ast.Position] = Map(LineColumnPosition(1, 1) -> leavePositions.headOption.map(p => p._1).getOrElse(LineColumnPosition(1, 1))) + + if (leavePositions.length > 1) { + leavePositions.sliding(2).foreach { + case Seq(a, b) => positions += (a._2 -> b._1) + } + } + + val ctx = new ReformatterContext(p.rawProgram, p.offsets, positions) super.pretty(defaultWidth, show(p, ctx)) } @@ -110,9 +123,19 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { } def show(r: Reformattable, ctx: ReformatterContext): Cont = { + println(s"${r.getClass}"); + println(s"${r}"); val trivia = r match { case p: PLeaf => { - val trivia = ctx.getTrivia(p.pos); + val trivia = ctx.posMap.get(p.pos._2).map(end => { + println(s"${p}"); + println(s"${p.pos._2}, ${end}"); + ctx.getTrivia(p.pos._2, end) + }).getOrElse({ + + Seq() + }); + println(trivia) val findNewlines = (trivia: Seq[Trivia]) => { var count = 0; breakable { @@ -145,7 +168,7 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { case _ => nil } - trivia <@@@> r.reformat(ctx) + r.reformat(ctx) <> trivia } def showAny(n: Any, ctx: ReformatterContext): Cont = { diff --git a/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala index 06614448d..7c6fb43a6 100644 --- a/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala @@ -273,6 +273,8 @@ case class PAdtType(adt: PIdnRef[PAdt], args: Option[PDelimited.Comma[PSym.Brack override def withTypeArguments(s: Seq[PType]): PAdtType = if (s.length == 0 && args.isEmpty) this else copy(args = Some(args.get.update(s)))(pos) override def copyExtraVars(from: Any): Unit = this.kind = from.asInstanceOf[PAdtType].kind + + override def reformat(ctx: ReformatterContext): Cont = show(adt, ctx) <> showOption(args, ctx) } object PAdtTypeKinds { From d7cd1a821aa1e2ee15f6a7eb83ab48491cb3f6b6 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Tue, 19 Nov 2024 12:43:34 +0100 Subject: [PATCH 10/47] More broken now but still more progress --- .../viper/silver/parser/FastParser.scala | 2 +- .../scala/viper/silver/parser/ParseAst.scala | 6 +- .../silver/parser/ReformatPrettyPrinter.scala | 55 +++++++++---------- 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/main/scala/viper/silver/parser/FastParser.scala b/src/main/scala/viper/silver/parser/FastParser.scala index fcdbb8158..77dfda79c 100644 --- a/src/main/scala/viper/silver/parser/FastParser.scala +++ b/src/main/scala/viper/silver/parser/FastParser.scala @@ -109,7 +109,7 @@ object FastParserCompanion { def newline[$: P]: P[PNewLine] = P((StringIn("\n\r") | "\n" | "\r") map {_ => PNewLine() }) def lineComment[$: P]: P[PComment] = { - P(("//" ~~ CharsWhile(_ != '\n').?.! ~~ ("\n" | End)).map { content => + P(("//" ~~ CharsWhile(_ != '\n').?.!).map { content => PComment(content, false) }) } diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index fdb25f589..1c37ef8fe 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -9,7 +9,7 @@ package viper.silver.parser import viper.silver.ast import viper.silver.ast.{FilePosition, HasLineColumn, Position} -import viper.silver.parser.ReformatPrettyPrinter.{formatTrivia, show, showAnnotations, showAny, showBody, showInvs, showOption, showPresPosts, showReturns, showSeq} +import viper.silver.parser.ReformatPrettyPrinter.{show, showAnnotations, showAny, showBody, showInvs, showOption, showPresPosts, showReturns, showSeq} import java.util.concurrent.atomic.{AtomicInteger, AtomicLong} import viper.silver.ast.utility.Visitor @@ -2115,8 +2115,8 @@ case class PNewLine() extends Trivia { case class PComment(content: String, block: Boolean) extends Trivia { override def reformat(ctx: ReformatterContext): Cont = if (block) { - text("/*") <> content <> text("*/") <> linebreak + text("/*") <> content <> text("*/") } else { - text("//") <> text(content) <> linebreak + text("//") <> text(content) } } \ No newline at end of file diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index d36c0433b..41a968c76 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -114,56 +114,55 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { } } - def formatTrivia(trivia: Seq[Trivia], ctx: ReformatterContext): Cont = { - trivia.filter({ - case _: PComment => true - case _ => false - }) - .foldLeft(nil)(_ <@@@> show(_, ctx)) - } - def show(r: Reformattable, ctx: ReformatterContext): Cont = { - println(s"${r.getClass}"); - println(s"${r}"); val trivia = r match { case p: PLeaf => { val trivia = ctx.posMap.get(p.pos._2).map(end => { - println(s"${p}"); println(s"${p.pos._2}, ${end}"); ctx.getTrivia(p.pos._2, end) }).getOrElse({ Seq() }); - println(trivia) - val findNewlines = (trivia: Seq[Trivia]) => { - var count = 0; - breakable { - for (el <- trivia) { - el match { - case _: PComment => break - case _: PNewLine => count += 1 - case _ => - } + + println(s"Trivia: ${trivia}"); + + var reformatted = nil + var newlines = 0; + var spaces = 0; + + for (t <- trivia) { + t match { + case p: PComment => { + val lw = if (newlines > 0) linebreak else if(spaces > 0) space else nil + reformatted = reformatted <> lw <> group(p.reformat(ctx)) + newlines = 0 + spaces = 0 } + case _: PNewLine => newlines += 1 + case _: PSpace => spaces += 1 + case _ => } + } - if (count > 1) linebreak else nil + if (newlines > 0) { + reformatted = reformatted <> linebreak } - val lw = findNewlines(trivia); - val tw = findNewlines(trivia.reverse); val hasComment = trivia exists { case _: PComment => true case _ => false } if (hasComment) { - lw <> formatTrivia(trivia, ctx) <> tw - } else { - lw + reformatted + } else { + if (newlines > 1) { + linebreak + } else { + nil + } } - }; case _ => nil } From 31b2d4efe8364f5514912816a0b4f4ac134c5be8 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Tue, 19 Nov 2024 12:55:36 +0100 Subject: [PATCH 11/47] Make reformatter context implicit --- .../scala/viper/silver/parser/ParseAst.scala | 346 +++++++++--------- .../viper/silver/parser/ParseAstKeyword.scala | 24 +- .../silver/parser/ReformatPrettyPrinter.scala | 51 ++- .../silver/plugin/ParserPluginTemplate.scala | 6 +- .../standard/adt/AdtPASTExtension.scala | 32 +- .../PredicateInstancePASTExtension.scala | 4 +- .../standard/refute/RefutePASTExtension.scala | 2 +- .../smoke/UnreachablePASTExtension.scala | 2 +- .../TerminationPASTExtension.scala | 10 +- 9 files changed, 237 insertions(+), 240 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 1c37ef8fe..83f94509f 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -238,7 +238,7 @@ trait PIdentifier extends PLeaf { } case class PIdnDef(name: String)(val pos: (Position, Position)) extends PNode with PIdentifier { - override def reformat(ctx: ReformatterContext): Cont = text(name) + override def reformat(implicit ctx: ReformatterContext): Cont = text(name) } trait PIdnUse extends PNode with PIdentifier { @@ -289,7 +289,7 @@ case class PIdnUseExp(name: String)(val pos: (Position, Position)) extends PIdnU override def rename(newName: String) = PIdnUseExp(newName)(pos) - override def reformatExp(ctx: ReformatterContext): Cont = text(name) + override def reformatExp(implicit ctx: ReformatterContext): Cont = text(name) } case class PIdnRef[T <: PDeclarationInner](name: String)(val pos: (Position, Position))(implicit val ctag: scala.reflect.ClassTag[T]) extends PIdnUseName[T] { override def rename(newName: String): PIdnUse = PIdnRef(newName)(pos) @@ -305,7 +305,7 @@ case class PIdnRef[T <: PDeclarationInner](name: String)(val pos: (Position, Pos } override def getExtraVals: Seq[Any] = Seq(pos, ctag) - override def reformat(ctx: ReformatterContext): Cont = name + override def reformat(implicit ctx: ReformatterContext): Cont = name } case class PVersionedIdnUseExp(name: String, version: String, separator: String = "@")(val pos: (Position, Position)) extends PIdnUseName[PTypedVarDecl] with PExp { @@ -323,7 +323,7 @@ case class PVersionedIdnUseExp(name: String, version: String, separator: String assert(typ.isGround) } - override def reformatExp(ctx: ReformatterContext): Cont = text(versionedName) + override def reformatExp(implicit ctx: ReformatterContext): Cont = text(versionedName) } /////////////////////////////////////////////////////////////////////////// @@ -333,7 +333,7 @@ trait PAnyFormalArgDecl extends PNode with PUnnamedTypedDeclaration with PPretty /** The declaration of an argument to a domain function. Not a `PDeclaration` as it will never clash. */ case class PDomainFunctionArg(name: Option[PIdnDef], c: Option[PSym.Colon], typ: PType)(val pos: (Position, Position)) extends PAnyFormalArgDecl { - override def reformat(ctx: ReformatterContext): Cont = showOption(name, ctx) <> showOption(c, ctx) <+@> show(typ, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = showOption(name) <> showOption(c) <+@> show(typ) } object PDomainFunctionArg { def apply(d: PIdnTypeBinding): PDomainFunctionArg = PDomainFunctionArg(Some(d.idndef), Some(d.c), d.typ)(d.pos) @@ -357,28 +357,28 @@ sealed trait PAssignableVarDecl extends PTypedVarDecl /** Any argument to a method, function or predicate. */ case class PFormalArgDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAnyFormalArgDecl with PTypedVarDecl with PMemberDeclaration with PMemberUniqueDeclaration { - override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <> show(c, ctx) <+> show(typ, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <> show(c) <+> show(typ) } object PFormalArgDecl { def apply(d: PIdnTypeBinding): PFormalArgDecl = PFormalArgDecl(d.idndef, d.c, d.typ)(d.pos) } /** The return arguments of methods. */ case class PFormalReturnDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAssignableVarDecl with PMemberDeclaration with PMemberUniqueDeclaration { - override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <> show(c, ctx) <+> show(typ, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <> show(c) <+> show(typ) } object PFormalReturnDecl { def apply(d: PIdnTypeBinding): PFormalReturnDecl = PFormalReturnDecl(d.idndef, d.c, d.typ)(d.pos) } case class PLogicalVarDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PTypedVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { - override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <> show(c, ctx) <+> show(typ, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <> show(c) <+> show(typ) } object PLogicalVarDecl { def apply(d: PIdnTypeBinding): PLogicalVarDecl = PLogicalVarDecl(d.idndef, d.c, d.typ)(d.pos) } /** Declaration of a local variable. */ case class PLocalVarDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAssignableVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { - override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <> show(c, ctx) <+> show(typ, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <> show(c) <+> show(typ) } object PLocalVarDecl { def apply(d: PIdnTypeBinding): PLocalVarDecl = PLocalVarDecl(d.idndef, d.c, d.typ)(d.pos) @@ -388,7 +388,7 @@ case class PFieldDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Posi override def annotations = decl.toSeq.flatMap(_.annotations) override def pretty = s"${idndef.pretty}: ${typ.pretty}" - override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <> show(c, ctx) <+> show(typ, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <> show(c) <+> show(typ) } object PFieldDecl { def apply(d: PIdnTypeBinding): PFieldDecl = PFieldDecl(d.idndef, d.c, d.typ)(d.pos) @@ -430,7 +430,7 @@ case class PPrimitiv[T <: PKeywordType](name: PReserved[T])(val pos: (Position, override def pretty = name.pretty - override def reformat(ctx: ReformatterContext): Cont = show(name, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(name) } case class PDomainType(domain: PIdnRef[PTypeDeclaration], args: Option[PDelimited.Comma[PSym.Bracket, PType]])(val pos: (Position, Position)) extends PGenericType with HasExtraVars { @@ -480,7 +480,7 @@ case class PDomainType(domain: PIdnRef[PTypeDeclaration], args: Option[PDelimite override def copyExtraVars(from: Any): Unit = this.kind = from.asInstanceOf[PDomainType].kind - override def reformat(ctx: ReformatterContext): Cont = show(domain, ctx) <> showOption(args, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(domain) <> showOption(args) } object PDomainTypeKinds { @@ -574,21 +574,21 @@ case class PSeqType(seq: PKw.Seq, elementType: PGrouped[PSym.Bracket, PType])(va override val genericName = "Seq" override def update(newType: PType) = copy(elementType = elementType.update(newType))(pos) - override def reformat(ctx: ReformatterContext): Cont = show(seq, ctx) <> show(elementType, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(seq) <> show(elementType) } case class PSetType(set: PKw.Set, elementType: PGrouped[PSym.Bracket, PType])(val pos: (Position, Position)) extends PType with PGenericCollectionType { override val genericName = "Set" override def update(newType: PType) = copy(elementType = elementType.update(newType))(pos) - override def reformat(ctx: ReformatterContext): Cont = show(set, ctx) <> show(elementType, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(set) <> show(elementType) } case class PMultisetType(multiset: PKw.Multiset, elementType: PGrouped[PSym.Bracket, PType])(val pos: (Position, Position)) extends PType with PGenericCollectionType { override val genericName = "Multiset" override def update(newType: PType) = copy(elementType = elementType.update(newType))(pos) - override def reformat(ctx: ReformatterContext): Cont = show(multiset, ctx) <> show(elementType, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(multiset) <> show(elementType) } case class PMapType(map: PKw.Map, typ: PGrouped[PSym.Bracket, PPairArgument[PType, PType]])(val pos: (Position, Position)) extends PType with PGenericType { @@ -606,7 +606,7 @@ case class PMapType(map: PKw.Map, typ: PGrouped[PSym.Bracket, PPairArgument[PTyp override def withTypeArguments(s: Seq[PType]): PMapType = copy(typ = typ.update(PPairArgument(s(0), typ.inner.c, s(1))(typ.inner.pos)))(pos) - override def reformat(ctx: ReformatterContext): Cont = show(map, ctx) <> show(typ, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(map) <> show(typ) } /** Exists temporarily after parsing and is replaced with @@ -619,7 +619,7 @@ case class PMacroType(use: PCall) extends PType { override def substitute(ts: PTypeSubstitution): PType = ??? override def subNodes: Seq[PType] = ??? - override def reformat(ctx: ReformatterContext): Cont = show(use, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(use) } /** Type used for internal nodes (e.g. typing predicate accesses) - should not be @@ -635,28 +635,28 @@ sealed trait PInternalType extends PType { case class PUnknown() extends PInternalType { override def isValidOrUndeclared = false override def pretty = "" - override def reformat(ctx: ReformatterContext): Cont = pretty + override def reformat(implicit ctx: ReformatterContext): Cont = pretty } case class PBoolImpureType() extends PInternalType { override def isValidOrUndeclared = true override def isPure: Boolean = false override def pretty = "" - override def reformat(ctx: ReformatterContext): Cont = pretty + override def reformat(implicit ctx: ReformatterContext): Cont = pretty } case class PBoolWandType() extends PInternalType { override def isValidOrUndeclared = true override def isPure: Boolean = false override def umbrella: Option[PType] = Some(TypeHelper.Impure) override def pretty = "" - override def reformat(ctx: ReformatterContext): Cont = pretty + override def reformat(implicit ctx: ReformatterContext): Cont = pretty } case class PBoolPredicateType() extends PInternalType { override def isValidOrUndeclared = true override def isPure: Boolean = false override def umbrella: Option[PType] = Some(TypeHelper.Impure) override def pretty = "" - override def reformat(ctx: ReformatterContext): Cont = pretty + override def reformat(implicit ctx: ReformatterContext): Cont = pretty } /** The type of a `PIdnUse` which refers to a function. Ensures that we get a @@ -672,12 +672,12 @@ case class PFunctionType(argTypes: Seq[PType], resultType: PType) extends PInter s"$argsPretty: ${resultType.pretty}" } - override def reformat(ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): Cont = { (if (argTypes.isEmpty) text("()") else - text("(") <> argTypes.map(show(_, ctx)).reduce(_ <> ", " <> _) <> text(")")) <> - text(": ") <> show(resultType, ctx) + text("(") <> argTypes.map(show(_)).reduce(_ <> ", " <> _) <> text(")")) <> + text(": ") <> show(resultType) } } @@ -709,15 +709,15 @@ trait PExp extends PNode with PPrettySubnodes with ReformattableExpression { // Note: We override the `reformat` for all expressions here, classes implementing this trait // should not override it. Instead, they should implement the `reformatExp` method. - override def reformat(ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): Cont = { // Unfortunately, we cannot just show exp.brackets, because then we end up in an // endless recursion. So instead, we need to add them manually. brackets match { case Some(b) => { if (b.l.isInstanceOf[PSym.Brace]) { - nest(defaultIndent, group(show(b.l, ctx) <@> this.reformatExp(ctx) <@> show(b.r, ctx))) + nest(defaultIndent, group(show(b.l) <@> this.reformatExp(ctx) <@> show(b.r))) } else { - show(b.l, ctx) <> this.reformatExp(ctx) <> show(b.r, ctx) + show(b.l) <> this.reformatExp(ctx) <> show(b.r) } } case None => this.reformatExp(ctx) @@ -729,7 +729,7 @@ case class PAnnotatedExp(annotation: PAnnotation, e: PExp)(val pos: (Position, P override def typeSubstitutions: collection.Seq[PTypeSubstitution] = e.typeSubstitutions override def forceSubstitution(ts: PTypeSubstitution): Unit = e.forceSubstitution(ts) - override def reformatExp(ctx: ReformatterContext): Cont = show(annotation, ctx) <@@> show(e, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(annotation) <@@> show(e) } trait PSubstitutionMap[S <: PSubstitutionMap[S]] { @@ -1039,8 +1039,8 @@ case class PCall(idnref: PIdnRef[PCallable], callArgs: PDelimited.Comma[PSym.Par args.foreach(_.forceSubstitution(ts)) } - override def reformatExp(ctx: ReformatterContext): Cont = show(idnref, ctx) <> - show(callArgs, ctx) <> typeAnnotated.map(e => show(e._1, ctx) <+> show(e._2, ctx)).getOrElse(nil) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(idnref) <> + show(callArgs) <> typeAnnotated.map(e => show(e._1) <+> show(e._2)).getOrElse(nil) } class PBinExp(val left: PExp, val op: PReserved[PBinaryOp], val right: PExp)(val pos: (Position, Position)) extends POpApp { @@ -1071,12 +1071,12 @@ class PBinExp(val left: PExp, val op: PReserved[PBinaryOp], val right: PExp)(val override def hashCode(): Int = viper.silver.utility.Common.generateHashCode(left, op.rs.operator, right) override def toString(): String = s"PBinExp($left,$op,$right)" - override def reformatExp(ctx: ReformatterContext): Cont = { + override def reformatExp(implicit ctx: ReformatterContext): Cont = { op.rs match { // Those operators look a bit better if they stick on the previous line case Iff | Implies | EqEq => - group(show(left, ctx) <+> show(op, ctx) <> nest(defaultIndent, line <> show(right, ctx))) - case _ => group(show(left, ctx) <@> show(op, ctx) <+> show(right, ctx)) + group(show(left) <+> show(op) <> nest(defaultIndent, line <> show(right))) + case _ => group(show(left) <@> show(op) <+> show(right)) } } @@ -1095,7 +1095,7 @@ case class PUnExp(op: PReserved[PUnaryOp], exp: PExp)(val pos: (Position, Positi override val args = Seq(exp) override val signatures = op.rs.signatures - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(exp, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> show(exp) } case class PCondExp(cond: PExp, q: PSymOp.Question, thn: PExp, c: PSymOp.Colon, els: PExp)(val pos: (Position, Position)) extends POpApp { @@ -1104,9 +1104,9 @@ case class PCondExp(cond: PExp, q: PSymOp.Question, thn: PExp, c: PSymOp.Colon, Map(POpApp.pArgS(0) -> Bool, POpApp.pArgS(2) -> POpApp.pArg(1), POpApp.pResS -> POpApp.pArg(1)) ) - override def reformatExp(ctx: ReformatterContext): Cont = show(cond, ctx) <+> show(q, ctx) <> - nest(defaultIndent, group(line <> show(thn, ctx) <+> - show(c, ctx) <> group(line <> show(els, ctx)))) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(cond) <+> show(q) <> + nest(defaultIndent, group(line <> show(thn) <+> + show(c) <> group(line <> show(els)))) } // Simple literals @@ -1124,11 +1124,11 @@ case class PIntLit(i: BigInt)(val pos: (Position, Position)) extends PSimpleLite typ = Int override def display = i.toString() - override def reformatExp(ctx: ReformatterContext): Cont = text(i.toString) + override def reformatExp(implicit ctx: ReformatterContext): Cont = text(i.toString) } case class PResultLit(result: PKw.Result)(val pos: (Position, Position)) extends PSimpleLiteral { - override def reformatExp(ctx: ReformatterContext): Cont = show(result, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(result) } case class PBoolLit(keyword: PReserved[PKeywordConstant])(val pos: (Position, Position)) extends PConstantLiteral { @@ -1138,13 +1138,13 @@ case class PBoolLit(keyword: PReserved[PKeywordConstant])(val pos: (Position, Po } typ = Bool - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) } case class PNullLit(keyword: PKw.Null)(val pos: (Position, Position)) extends PConstantLiteral { typ = Ref - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) } sealed trait PHeapOpApp extends POpApp @@ -1165,7 +1165,7 @@ case class PFieldAccess(rcv: PExp, dot: PSymOp.Dot, idnref: PIdnRef[PFieldDecl]) case _ => List() } - override def reformatExp(ctx: ReformatterContext): Cont = show(rcv, ctx) <> show(dot, ctx) <> show(idnref, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(rcv) <> show(dot) <> show(idnref) } case class PUnfolding(unfolding: PKwOp.Unfolding, acc: PAccAssertion, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { @@ -1173,7 +1173,7 @@ case class PUnfolding(unfolding: PKwOp.Unfolding, acc: PAccAssertion, in: PKwOp. override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Predicate, POpApp.pResS -> POpApp.pArg(1))) - override def reformatExp(ctx: ReformatterContext): Cont = show(unfolding, ctx) <+> show(acc, ctx) <+> show(in, ctx) <> nest(defaultIndent, group(line <> show(exp, ctx))) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(unfolding) <+> show(acc) <+> show(in) <> nest(defaultIndent, group(line <> show(exp))) } case class PApplying(applying: PKwOp.Applying, wand: PExp, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { @@ -1181,7 +1181,7 @@ case class PApplying(applying: PKwOp.Applying, wand: PExp, in: PKwOp.In, exp: PE override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Wand, POpApp.pResS -> POpApp.pArg(1))) - override def reformatExp(ctx: ReformatterContext): Cont = show(applying, ctx) <+> show(wand, ctx) <+> show(in, ctx) <> nest(defaultIndent, group(line <> show(exp, ctx))) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(applying) <+> show(wand) <+> show(in) <> nest(defaultIndent, group(line <> show(exp))) } case class PAsserting(asserting: PKwOp.Asserting, a: PExp, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { @@ -1189,9 +1189,9 @@ case class PAsserting(asserting: PKwOp.Asserting, a: PExp, in: PKwOp.In, exp: PE override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Impure, POpApp.pResS -> POpApp.pArg(1))) - override def reformatExp(ctx: ReformatterContext): Cont = show(asserting, ctx) <+> - nest(defaultIndent, group(line <> show(a, ctx))) <+> - show(in, ctx) <> nest(defaultIndent, group(line <> show(exp, ctx))) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(asserting) <+> + nest(defaultIndent, group(line <> show(a))) <+> + show(in) <> nest(defaultIndent, group(line <> show(exp))) } sealed trait PBinder extends PExp with PScope { @@ -1213,7 +1213,7 @@ sealed trait PBinder extends PExp with PScope { case class PTrigger(exp: PDelimited.Comma[PSym.Brace, PExp])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { override def pretty = exp.pretty - override def reformat(ctx: ReformatterContext): Cont = show(exp, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(exp) } sealed trait PQuantifier extends PBinder { @@ -1225,21 +1225,21 @@ sealed trait PQuantifier extends PBinder { } case class PExists(keyword: PKw.Exists, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier { - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> show(vars, ctx) <+> - show(c, ctx) <> nest(defaultIndent, group(line <> (showSeq(triggers, ctx) <+@> show(body, ctx)))) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <+> show(vars) <+> + show(c) <> nest(defaultIndent, group(line <> (showSeq(triggers) <+@> show(body)))) } case class PForall(keyword: PKw.Forall, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier { - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> show(vars, ctx) <+> - show(c, ctx) <> nest(defaultIndent, group(line <> group(showSeq(triggers, ctx) <+@> show(body, ctx)))) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <+> show(vars) <+> + show(c) <> nest(defaultIndent, group(line <> group(showSeq(triggers) <+@> show(body)))) } case class PForPerm(keyword: PKw.Forperm, vars: PDelimited[PLogicalVarDecl, PSym.Comma], accessRes: PGrouped[PSym.Bracket, PResourceAccess], c: PSym.ColonColon, body: PExp)(val pos: (Position, Position)) extends PQuantifier { val triggers: Seq[PTrigger] = Seq() - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> - show(vars, ctx) <+> show(accessRes, ctx) <+> show(c, ctx) <> - nest(defaultIndent, group(line <> show(body, ctx))) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <+> + show(vars) <+> show(accessRes) <+> show(c) <> + nest(defaultIndent, group(line <> show(body))) } /* Let-expressions `let x == e1 in e2` are represented by the nested structure @@ -1263,8 +1263,8 @@ case class PLet(l: PKwOp.Let, variable: PIdnDef, eq: PSymOp.EqEq, exp: PGrouped. typ = nestedScope.body.typ } - override def reformatExp(ctx: ReformatterContext): Cont = show(l, ctx) <+> show(variable, ctx) <+> - show(eq, ctx) <+> show(exp, ctx) <+> show(in, ctx) <> group(line <> show(nestedScope, ctx)) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(l) <+> show(variable) <+> + show(eq) <+> show(exp) <+> show(in) <> group(line <> show(nestedScope)) } case class PLetNestedScope(body: PExp)(val pos: (Position, Position)) extends PTypedVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { @@ -1272,7 +1272,7 @@ case class PLetNestedScope(body: PExp)(val pos: (Position, Position)) extends PT override def idndef: PIdnDef = outerLet.variable override def typ: PType = outerLet.exp.inner.typ - override def reformat(ctx: ReformatterContext): Cont = show(body, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(body) } // [in,ex] @@ -1284,20 +1284,20 @@ case class PInhaleExhaleExp(l: PSymOp.LBracket, in: PExp, c: PSymOp.Comma, ex: P Map(POpApp.pArgS(0) -> Impure, POpApp.pArgS(1) -> Impure, POpApp.pResS -> Impure), ) - override def reformatExp(ctx: ReformatterContext): Cont = show(l, ctx) <> - show(in, ctx) <> show(c, ctx) <+> show(ex, ctx) <> show(r, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(l) <> + show(in) <> show(c) <+> show(ex) <> show(r) } case class PNoPerm(keyword: PKw.None)(val pos: (Position, Position)) extends PConstantLiteral { typ = Perm - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) } case class PFullPerm(keyword: PKw.Write)(val pos: (Position, Position)) extends PConstantLiteral { typ = Perm - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) } object PFullPerm { def implied(): PFullPerm = PFullPerm(PReserved(PKw.Write)(NoPosition, NoPosition))(NoPosition, NoPosition) @@ -1306,13 +1306,13 @@ object PFullPerm { case class PWildcard(keyword: PKw.Wildcard)(val pos: (Position, Position)) extends PConstantLiteral { typ = Perm - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) } case class PEpsilon(keyword: PKw.Epsilon)(val pos: (Position, Position)) extends PConstantLiteral { typ = Perm - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) } trait PCallKeyword extends POpApp { @@ -1325,14 +1325,14 @@ case class PCurPerm(op: PKwOp.Perm, res: PGrouped.Paren[PResourceAccess])(val po Map(POpApp.pResS -> Perm) ) - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <+> show(res, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <+> show(res) } case class PPairArgument[+T, +U](first: T, c: PSym.Comma, second: U)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(ctx: ReformatterContext): Cont = showAny(first, ctx) <> show(c, ctx) <+> showAny(second, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = showAny(first) <> show(c) <+> showAny(second) } case class PMaybePairArgument[+T, +U](first: T, second: Option[(PSym.Comma, U)])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(ctx: ReformatterContext): Cont = showAny(first, ctx) <> second.map(a => show(a._1, ctx) <+> showAny(a._2, ctx)).getOrElse(nil) + override def reformat(implicit ctx: ReformatterContext): Cont = showAny(first) <> second.map(a => show(a._1) <+> showAny(a._2)).getOrElse(nil) } sealed trait PAccAssertion extends PExp { @@ -1349,7 +1349,7 @@ case class PAccPred(op: PKwOp.Acc, amount: PGrouped.Paren[PMaybePairArgument[PLo def perm = amount.inner.second.map(_._2).getOrElse(PFullPerm.implied()) override val args = Seq(loc, perm) - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(amount, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> show(amount) } case class POldExp(op: PKwOp.Old, label: Option[PGrouped[PSym.Bracket, Either[PKw.Lhs, PIdnRef[PLabel]]]], e: PGrouped.Paren[PExp])(val pos: (Position, Position)) extends PCallKeyword with PHeapOpApp { @@ -1357,7 +1357,7 @@ case class POldExp(op: PKwOp.Old, label: Option[PGrouped[PSym.Bracket, Either[PK override def requirePure = args override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pResS -> POpApp.pArg(0))) - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> showOption(label, ctx) <> show(e, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> showOption(label) <> show(e) } case class PDebugLabelledOldExp(op: PKwOp.Old, label: PVersionedIdnUseExp, e: PExp)(val pos: (Position, Position)) extends PCallKeyword with PHeapOpApp { @@ -1367,7 +1367,7 @@ case class PDebugLabelledOldExp(op: PKwOp.Old, label: PVersionedIdnUseExp, e: PE override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pResS -> POpApp.pArg(0))) - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(label, ctx) <> show(e, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> show(label) <> show(e) } sealed trait PCollectionLiteral extends PCallKeyword { @@ -1415,11 +1415,11 @@ sealed trait PSeqLiteral extends PCollectionLiteral { } case class PEmptySeq(op: PKwOp.Seq, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PSeqLiteral with PEmptyCollectionLiteral { - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> showOption(pAnnotatedType, ctx) <> show(callArgs, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> showOption(pAnnotatedType) <> show(callArgs) } case class PExplicitSeq(op: PKwOp.Seq, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PSeqLiteral with PExplicitCollectionLiteral { - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(callArgs, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> show(callArgs) } // [low..high) @@ -1429,8 +1429,8 @@ case class PRangeSeq(l: PSymOp.LBracket, low: PExp, ds: PSymOp.DotDot, high: PEx override val signatures: List[PTypeSubstitution] = List( Map(POpApp.pArgS(0) -> Int, POpApp.pArgS(1) -> Int, POpApp.pResS -> MakeSeq(Int))) - override def reformatExp(ctx: ReformatterContext): Cont = show(l, ctx) <> show(low, ctx) <> show(ds, ctx) <> - show(high, ctx) <> show(r, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(l) <> show(low) <> show(ds) <> + show(high) <> show(r) } // base[idx] @@ -1445,8 +1445,8 @@ case class PLookup(base: PExp, l: PSymOp.LBracket, idx: PExp, r: PSymOp.RBracket Map(POpApp.pArgS(0) -> MakeMap(keyType, POpApp.pRes)) ) - override def reformatExp(ctx: ReformatterContext): Cont = show(base, ctx) <> show(l, ctx) <> - show(idx, ctx) <> show(r, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(base) <> show(l) <> + show(idx) <> show(r) } case class PSeqSlice(seq: PExp, l: PSymOp.LBracket, s: Option[PExp], d: PSymOp.DotDot, e: Option[PExp], r: PSymOp.RBracket)(val pos: (Position, Position)) extends POpApp { @@ -1462,8 +1462,8 @@ case class PSeqSlice(seq: PExp, l: PSymOp.LBracket, s: Option[PExp], d: PSymOp.D case (None, None) => Map() })) - override def reformatExp(ctx: ReformatterContext): Cont = show(seq, ctx) <> show(l, ctx) <> - showOption(s, ctx) <> show(d, ctx) <> showOption(e, ctx) <> show(r, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(seq) <> show(l) <> + showOption(s) <> show(d) <> showOption(e) <> show(r) } case class PUpdate(base: PExp, l: PSymOp.LBracket, key: PExp, a: PSymOp.Assign, value: PExp, r: PSymOp.RBracket)(val pos: (Position, Position)) extends POpApp { @@ -1478,8 +1478,8 @@ case class PUpdate(base: PExp, l: PSymOp.LBracket, key: PExp, a: PSymOp.Assign, Map(POpApp.pArgS(0) -> MakeMap(keyType, elementType), POpApp.pResS -> MakeMap(keyType, elementType)) ) - override def reformatExp(ctx: ReformatterContext): Cont = show(base, ctx) <> show(l, ctx) <> - show(key, ctx) <+> show(a, ctx) <+> show(value, ctx) <> show(r, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(base) <> show(l) <> + show(key) <+> show(a) <+> show(value) <> show(r) } case class PSize(l: PSymOp.Or, seq: PExp, r: PSymOp.Or)(val pos: (Position, Position)) extends POpApp { @@ -1497,8 +1497,8 @@ case class PSize(l: PSymOp.Or, seq: PExp, r: PSymOp.Or)(val pos: (Position, Posi Map(POpApp.pArgS(0) -> MakeMap(keyType, elementType), POpApp.pResS -> Int) ) - override def reformatExp(ctx: ReformatterContext): Cont = show(l, ctx) <> - show(seq, ctx) <> show(r, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(l) <> + show(seq) <> show(r) } sealed trait PSetLiteral extends PCollectionLiteral { @@ -1506,12 +1506,12 @@ sealed trait PSetLiteral extends PCollectionLiteral { } case class PEmptySet(op: PKwOp.Set, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PSetLiteral with PEmptyCollectionLiteral { - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> - showOption(pAnnotatedType, ctx) <> show(callArgs, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> + showOption(pAnnotatedType) <> show(callArgs) } case class PExplicitSet(op: PKwOp.Set, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PSetLiteral with PExplicitCollectionLiteral { - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(callArgs, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> show(callArgs) } sealed trait PMultiSetLiteral extends PCollectionLiteral { @@ -1519,13 +1519,13 @@ sealed trait PMultiSetLiteral extends PCollectionLiteral { } case class PEmptyMultiset(op: PKwOp.Multiset, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PMultiSetLiteral with PEmptyCollectionLiteral { - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> - showOption(pAnnotatedType, ctx) <> show(callArgs, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> + showOption(pAnnotatedType) <> show(callArgs) } case class PExplicitMultiset(op: PKwOp.Multiset, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PMultiSetLiteral with PExplicitCollectionLiteral { - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> - show(callArgs, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> + show(callArgs) } @@ -1556,8 +1556,8 @@ case class PEmptyMap(op: PKwOp.Map, pAnnotatedType: Option[PGrouped[PSym.Bracket def explicitType: Option[(PType, PType)] = pAnnotatedType.map(t => (t.inner.first, t.inner.second)) - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> - showOption(pAnnotatedType, ctx) <> show(callArgs, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> + showOption(pAnnotatedType) <> show(callArgs) } case class PExplicitMap(op: PKwOp.Map, callArgs: PDelimited.Comma[PSym.Paren, PMaplet])(val pos: (Position, Position)) extends PMapLiteral { @@ -1571,7 +1571,7 @@ case class PExplicitMap(op: PKwOp.Map, callArgs: PDelimited.Comma[PSym.Paren, PM }.toMap ) - override def reformatExp(ctx: ReformatterContext): Cont = show(op, ctx) <> show(callArgs, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> show(callArgs) } /** @@ -1584,7 +1584,7 @@ case class PMaplet(key: PExp, a: PSymOp.Assign, value: PExp)(val pos: (Position, POpApp.pResS -> MakeMap(POpApp.pArg(0), POpApp.pArg(1)) )) - override def reformatExp(ctx: ReformatterContext): Cont = show(key, ctx) <+> show(a, ctx) <+> show(value, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(key) <+> show(a) <+> show(value) } case class PMapDomain(keyword: PKwOp.Domain, base: PGrouped.Paren[PExp])(val pos: (Position, Position)) extends POpApp { @@ -1599,7 +1599,7 @@ case class PMapDomain(keyword: PKwOp.Domain, base: PGrouped.Paren[PExp])(val pos POpApp.pResS -> MakeSet(keyType) )) - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <> show(base, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <> show(base) } case class PMapRange(keyword: PKwOp.Range, base: PGrouped.Paren[PExp])(val pos: (Position, Position)) extends POpApp { @@ -1614,7 +1614,7 @@ case class PMapRange(keyword: PKwOp.Range, base: PGrouped.Paren[PExp])(val pos: POpApp.pResS -> MakeSet(valueType) )) - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <> show(base, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <> show(base) } @@ -1623,13 +1623,13 @@ case class PMapRange(keyword: PKwOp.Range, base: PGrouped.Paren[PExp])(val pos: trait PStmt extends PNode with PPrettySubnodes case class PAnnotatedStmt(annotation: PAnnotation, stmt: PStmt)(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(annotation, ctx) <@@> show(stmt, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(annotation) <@@> show(stmt) } case class PSeqn(ss: PDelimited.Block[PStmt])(val pos: (Position, Position)) extends PStmt with PScope { override def pretty = ss.prettyLines - override def reformat(ctx: ReformatterContext): Cont = show(ss, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(ss) } /** @@ -1639,99 +1639,99 @@ case class PSeqn(ss: PDelimited.Block[PStmt])(val pos: (Position, Position)) ext * before translation. */ case class PMacroSeqn(ss: PDelimited.Block[PStmt])(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(ss, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(ss) } case class PFold(fold: PKw.Fold, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(fold, ctx) <+> show(e, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(fold) <+> show(e) } case class PUnfold(unfold: PKw.Unfold, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(unfold, ctx) <+> show(e, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(unfold) <+> show(e) } case class PPackageWand(pckg: PKw.Package, e: PExp, proofScript: Option[PSeqn])(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(pckg, ctx) <+> show(e, ctx) <+> - showOption(proofScript, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(pckg) <+> show(e) <+> + showOption(proofScript) } case class PApplyWand(apply: PKw.Apply, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(apply, ctx) <+> show(e, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(apply) <+> show(e) } case class PExhale(exhale: PKw.Exhale, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(exhale, ctx) <+> show(e, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(exhale) <+> show(e) } case class PAssert(assert: PKw.Assert, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(assert, ctx) <+> show(e, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(assert) <+> show(e) } case class PAssume(assume: PKw.Assume, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(assume, ctx) <+> show(e, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(assume) <+> show(e) } case class PInhale(inhale: PKw.Inhale, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(inhale, ctx) <+> show(e, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(inhale) <+> show(e) } /** Can also represent a method call or statement macro with no `:=` when `targets` is empty. */ case class PAssign(targets: PDelimited[PExp with PAssignTarget, PSym.Comma], op: Option[PSymOp.Assign], rhs: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(targets, ctx) <+@> showOption(op, ctx) <+@> nest(defaultIndent, show(rhs, ctx)) + override def reformat(implicit ctx: ReformatterContext): Cont = show(targets) <+@> showOption(op) <+@> nest(defaultIndent, show(rhs)) } sealed trait PIfContinuation extends PStmt case class PIf(keyword: PReserved[PKeywordIf], cond: PGrouped.Paren[PExp], thn: PSeqn, els: Option[PIfContinuation])(val pos: (Position, Position)) extends PStmt with PIfContinuation { - override def reformat(ctx: ReformatterContext): Cont = show(keyword, ctx) <+> show(cond, ctx) <> - showBody(show(thn, ctx), false) <+@> showBody(showOption(els, ctx), false) + override def reformat(implicit ctx: ReformatterContext): Cont = show(keyword) <+> show(cond) <> + showBody(show(thn), false) <+@> showBody(showOption(els), false) } case class PElse(k: PKw.Else, els: PSeqn)(val pos: (Position, Position)) extends PStmt with PIfContinuation { - override def reformat(ctx: ReformatterContext): Cont = { - show(k, ctx) <+> showBody(show(els, ctx), false) + override def reformat(implicit ctx: ReformatterContext): Cont = { + show(k) <+> showBody(show(els), false) } } case class PWhile(keyword: PKw.While, cond: PGrouped.Paren[PExp], invs: PDelimited[PSpecification[PKw.InvSpec], Option[PSym.Semi]], body: PSeqn)(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = { - show(keyword, ctx) <> show(cond, ctx) <+> - showInvs(invs, ctx) <> showBody(show(body, ctx), !invs.isEmpty) + override def reformat(implicit ctx: ReformatterContext): Cont = { + show(keyword) <> show(cond) <+> + showInvs(invs) <> showBody(show(body), !invs.isEmpty) } } case class PVars(keyword: PKw.Var, vars: PDelimited[PLocalVarDecl, PSym.Comma], init: Option[(PSymOp.Assign, PExp)])(val pos: (Position, Position)) extends PStmt { def assign: Option[PAssign] = init map (i => PAssign(vars.update(vars.toSeq.map(_.toIdnUse)), Some(i._1), i._2)(pos)) - override def reformat(ctx: ReformatterContext): Cont = - show(keyword, ctx) <+> show(vars, ctx) <> - init.map(s => nest(defaultIndent, group(nil <+> show(s._1, ctx) <@> show(s._2, ctx)))).getOrElse(nil) + override def reformat(implicit ctx: ReformatterContext): Cont = + show(keyword) <+> show(vars) <> + init.map(s => nest(defaultIndent, group(nil <+> show(s._1) <@> show(s._2)))).getOrElse(nil) } case class PLabel(label: PKw.Label, idndef: PIdnDef, invs: PDelimited[PSpecification[PKw.InvSpec], Option[PSym.Semi]])(val pos: (Position, Position)) extends PStmt with PMemberDeclaration with PBackwardDeclaration { - override def reformat(ctx: ReformatterContext): Cont = show(label, ctx) <+> show(idndef, ctx) <+> show(invs, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(label) <+> show(idndef) <+> show(invs) } case class PGoto(goto: PKw.Goto, target: PIdnRef[PLabel])(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(goto, ctx) <+> show(target, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(goto) <+> show(target) } // Should this be sealed? sealed trait PTypeDeclaration extends PDeclarationInner case class PTypeVarDecl(idndef: PIdnDef)(val pos: (Position, Position)) extends PMemberDeclaration with PTypeDeclaration with PPrettySubnodes { - override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) } case class PSkip()(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = text("") + override def reformat(implicit ctx: ReformatterContext): Cont = text("") } case class PQuasihavoc(quasihavoc: PKw.Quasihavoc, lhs: Option[(PExp, PSymOp.Implies)], e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(ctx: ReformatterContext): Cont = show(quasihavoc, ctx) <+@> showOption(lhs, ctx) <+@> show(e, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(quasihavoc) <+@> showOption(lhs) <+@> show(e) } case class PQuasihavocall(quasihavocall: PKw.Quasihavocall, vars: PDelimited[PLogicalVarDecl, PSym.Comma], colons: PSym.ColonColon, lhs: Option[(PExp, PSymOp.Implies)], e: PExp)(val pos: (Position, Position)) extends PStmt with PScope { - override def reformat(ctx: ReformatterContext): Cont = show(quasihavocall, ctx) <+@> showOption(lhs, ctx) <+@> show(e, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(quasihavocall) <+@> showOption(lhs) <+@> show(e) } /* new(f1, ..., fn) or new(*) */ @@ -1739,7 +1739,7 @@ case class PNewExp(keyword: PKw.New, fields: PGrouped.Paren[Either[PSym.Star, PD override final val typeSubstitutions = Seq(PTypeSubstitution.id) def forceSubstitution(ts: PTypeSubstitution) = {} - override def reformatExp(ctx: ReformatterContext): Cont = show(keyword, ctx) <> show(fields, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <> show(fields) } sealed trait PScope extends PNode { @@ -1812,7 +1812,7 @@ trait PTypedDeclaration extends PUnnamedTypedDeclaration case class PBracedExp(e: PGrouped[PSym.Brace, PExp])(val pos: (Position, Position)) extends PNode { override def pretty = s" ${e.l.pretty}\n ${e.inner.pretty.replace("\n", "\n ")}\n${e.r.pretty}" - override def reformat(ctx: ReformatterContext): Cont = show(e, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(e) } trait PCallable extends PDeclarationInner { @@ -1881,11 +1881,11 @@ case class PProgram(imported: Seq[PProgram], members: Seq[PMember])(val pos: (Po prefix + m + "\n\n" + i } - override def reformat(ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): Cont = { println(s"whole program ${this.members}"); - members.map(show(_, ctx)).foldLeft(nil)((acc, n) => acc <@@> n) + members.map(show(_)).foldLeft(nil)((acc, n) => acc <@@> n) // Don't forget comments that appear after any nodes! -// formatTrivia(ctx.getTriviaByByteOffset(rawProgram.length), ctx) +// formatTrivia(ctx.getTriviaByByteOffset(rawProgram.length)) } // Pretty print members in a specific order @@ -1909,16 +1909,16 @@ case class PImport(annotations: Seq[PAnnotation], imprt: PKw.Import, file: PStri var resolved: Option[Path] = None def declares = Nil - override def reformat(ctx: ReformatterContext): Cont = show(imprt, ctx) <+> show(file, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(imprt) <+> show(file) } case class PDefineParam(idndef: PIdnDef)(val pos: (Position, Position)) extends PNode with PLocalDeclaration with PPrettySubnodes { - override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) } case class PDefine(annotations: Seq[PAnnotation], define: PKw.Define, idndef: PIdnDef, parameters: Option[PDelimited.Comma[PSym.Paren, PDefineParam]], body: PNode)(val pos: (FilePosition, FilePosition)) extends PSingleMember with PStmt with PNameAnalyserOpaque { - override def reformat(ctx: ReformatterContext): Cont = { - showAnnotations(annotations, ctx) <@@> show(define, ctx) <+> show(idndef, ctx) <> showOption(parameters, ctx) <+> show(body, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = { + showAnnotations(annotations) <@@> show(define) <+> show(idndef) <> showOption(parameters) <+> show(body) } } @@ -1926,18 +1926,18 @@ case class PDomain(annotations: Seq[PAnnotation], domain: PKw.Domain, idndef: PI (val pos: (Position, Position)) extends PSingleMember with PTypeDeclaration with PPrettySubnodes { def typVarsSeq: Seq[PTypeVarDecl] = typVars.map(_.inner.toSeq).getOrElse(Nil) - override def reformat(ctx: ReformatterContext): Cont = { - showAnnotations(annotations, ctx) <@@> show(domain, ctx) <+> - show(idndef, ctx) <> showOption(typVars, ctx) <> - (if (interpretations.isEmpty) nil else nest(defaultIndent, linebreak <> showOption(interpretations, ctx))) <> - showBody(show(members, ctx), !interpretations.isEmpty) + override def reformat(implicit ctx: ReformatterContext): Cont = { + showAnnotations(annotations) <@@> show(domain) <+> + show(idndef) <> showOption(typVars) <> + (if (interpretations.isEmpty) nil else nest(defaultIndent, linebreak <> showOption(interpretations))) <> + showBody(show(members), !interpretations.isEmpty) } } case class PDomainFunctionInterpretation(k: PKw.Interpretation, i: PStringLiteral)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { override def pretty = s"\n ${super.pretty}" - override def reformat(ctx: ReformatterContext): Cont = show(k, ctx) <+> show(i, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(k) <+> show(i) } trait PDomainMember extends PScope { def domain: PDomain = getAncestor[PDomain].get @@ -1945,14 +1945,14 @@ trait PDomainMember extends PScope { case class PDomainFunction(annotations: Seq[PAnnotation], unique: Option[PKw.Unique], keyword: PKw.FunctionD, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PDomainFunctionArg], c: PSym.Colon, resultType: PType, interpretation: Option[PDomainFunctionInterpretation])(val pos: (Position, Position)) extends PSingleMember with PNoSpecsFunction with PDomainMember with PPrettySubnodes { override def body = None - override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> showOption(unique, ctx) <+@> - show(keyword, ctx) <+> show(idndef, ctx) <+> show(args, ctx) <> - show(c, ctx) <+> show(resultType, ctx) <+> showOption(interpretation, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> showOption(unique) <+@> + show(keyword) <+> show(idndef) <+> show(args) <> + show(c) <+> show(resultType) <+> showOption(interpretation) } case class PAxiom(annotations: Seq[PAnnotation], axiom: PKw.Axiom, idndef: Option[PIdnDef], exp: PBracedExp)(val pos: (Position, Position)) extends PDomainMember with PPrettySubnodes { - override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> show(axiom, ctx) <+> - showOption(idndef, ctx) <+> show(exp, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> show(axiom) <+> + showOption(idndef) <+> show(exp) } case class PDomainMembers(funcs: PDelimited[PDomainFunction, Option[PSym.Semi]], axioms: PDelimited[PAxiom, Option[PSym.Semi]])(val pos: (Position, Position), val original: PDomainMembers1) extends PNode { override def pretty: String = { @@ -1963,30 +1963,30 @@ case class PDomainMembers(funcs: PDelimited[PDomainFunction, Option[PSym.Semi]], override def getExtraVals: Seq[Any] = Seq(pos, original) - override def reformat(ctx: ReformatterContext): Cont = show(original, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(original) } case class PDomainInterpretation(name: PRawString, c: PSym.Colon, lit: PStringLiteral)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(ctx: ReformatterContext): Cont = show(name, ctx) <> show(c, ctx) <+> show(lit, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(name) <> show(c) <+> show(lit) } case class PDomainInterpretations(k: PReserved[PKeywordLang], m: PDelimited.Comma[PSym.Paren, PDomainInterpretation])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { def interps: Map[String, String] = m.inner.toSeq.map(i => i.name.str -> i.lit.str).toMap - override def reformat(ctx: ReformatterContext): Cont = show(k, ctx) <+> show(m, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(k) <+> show(m) } trait PDomainMember1 extends PNode with PPrettySubnodes case class PDomainFunction1(annotations: Seq[PAnnotation], unique: Option[PKw.Unique], function: PKw.FunctionD, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PDomainFunctionArg], c: PSym.Colon, typ: PType, interpretation: Option[PDomainFunctionInterpretation], s: Option[PSym.Semi])(val pos: (Position, Position)) extends PDomainMember1 { - override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> showOption(unique, ctx) <+@> - show(function, ctx) <+@> showOption(interpretation, ctx) <+> - show(idndef, ctx) <> show(args, ctx) <> show(c, ctx) <+> show(typ, ctx) <+> showOption(s, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> showOption(unique) <+@> + show(function) <+@> showOption(interpretation) <+> + show(idndef) <> show(args) <> show(c) <+> show(typ) <+> showOption(s) } case class PAxiom1(annotations: Seq[PAnnotation], axiom: PKw.Axiom, idndef: Option[PIdnDef], exp: PBracedExp, s: Option[PSym.Semi])(val pos: (Position, Position)) extends PDomainMember1 { - override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> show(axiom, ctx) <+@> - showOption(idndef, ctx) <+@> show(exp, ctx) <> showOption(s, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> show(axiom) <+@> + showOption(idndef) <+@> show(exp) <> showOption(s) } case class PDomainMembers1(members: Seq[PDomainMember1])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(ctx: ReformatterContext): Cont = if (members.isEmpty) nil else members.map(m => show(m, ctx)) + override def reformat(implicit ctx: ReformatterContext): Cont = if (members.isEmpty) nil else members.map(m => show(m)) .reduce(_ <> linebreak <> _) } @@ -1994,33 +1994,33 @@ case class PDomainMembers1(members: Seq[PDomainMember1])(val pos: (Position, Pos case class PFields(annotations: Seq[PAnnotation], field: PKw.Field, fields: PDelimited[PFieldDecl, PSym.Comma], s: Option[PSym.Semi])(val pos: (Position, Position)) extends PMember with PPrettySubnodes { override def declares: Seq[PGlobalDeclaration] = fields.toSeq - override def reformat(ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): Cont = { // println(s"PFields"); // println(s"---------------------------"); // println(s"annotation: ${annotation}"); // println(s"field: ${field}"); // println(s"fields: ${fields}"); // println(s"s: ${s}"); - show(field, ctx) <+> show(fields, ctx) <> showOption(s, ctx) + show(field) <+> show(fields) <> showOption(s) } } case class PSpecification[+T <: PKw.Spec](k: PReserved[PKw.Spec], e: PExp)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { override def pretty: String = "\n " + super.pretty - override def reformat(ctx: ReformatterContext): Cont = show(k, ctx) <+> show(e, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(k) <+> show(e) } case class PFunction(annotations: Seq[PAnnotation], keyword: PKw.Function, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PFormalArgDecl], c: PSym.Colon, resultType: PType, pres: PDelimited[PSpecification[PKw.PreSpec], Option[PSym.Semi]], posts: PDelimited[PSpecification[PKw.PostSpec], Option[PSym.Semi]], body: Option[PBracedExp]) (val pos: (Position, Position)) extends PSingleMember with PAnyFunction with PGlobalCallableNamedArgs with PPrettySubnodes { - override def reformat(ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): Cont = { // TODO: Add PFunctioNType println(s"PFunction"); println(s"---------------------------"); println(s"body ${body}"); - showAnnotations(annotations, ctx) <@@> show(keyword, ctx) <+> show(idndef, ctx) <> - show(args, ctx) <> show(c, ctx) <+> show(resultType, ctx) <> - showPresPosts(pres, posts, ctx) <> showBody(showOption(body, ctx), !(pres.isEmpty && posts.isEmpty)) + showAnnotations(annotations) <@@> show(keyword) <+> show(idndef) <> + show(args) <> show(c) <+> show(resultType) <> + showPresPosts(pres, posts) <> showBody(showOption(body), !(pres.isEmpty && posts.isEmpty)) } } @@ -2029,8 +2029,8 @@ case class PPredicate(annotations: Seq[PAnnotation], keyword: PKw.Predicate, idn override def c = PReserved.implied(PSym.Colon) override def resultType = Predicate - override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> show(keyword, ctx) <+> show(idndef, ctx) <> - show(args, ctx) <> showBody(showOption(body, ctx), false) + override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> show(keyword) <+> show(idndef) <> + show(args) <> showBody(showOption(body), false) } case class PMethod(annotations: Seq[PAnnotation], keyword: PKw.Method, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PFormalArgDecl], returns: Option[PMethodReturns], pres: PDelimited[PSpecification[PKw.PreSpec], Option[PSym.Semi]], posts: PDelimited[PSpecification[PKw.PostSpec], Option[PSym.Semi]], body: Option[PSeqn]) @@ -2038,7 +2038,7 @@ case class PMethod(annotations: Seq[PAnnotation], keyword: PKw.Method, idndef: P def formalReturns: Seq[PFormalReturnDecl] = returns.map(_.formalReturns.inner.toSeq).getOrElse(Nil) override def returnNodes = returns.toSeq - override def reformat(ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): Cont = { // TODO: Test annotations // println(s"PMethod"); // println(s"---------------------------"); @@ -2048,13 +2048,13 @@ case class PMethod(annotations: Seq[PAnnotation], keyword: PKw.Method, idndef: P // println(s"posts ${posts}"); // println(s"body ${body}"); // println(s"keyword pos: ${keyword.pos}"); - showAnnotations(annotations, ctx) <@@> show(keyword, ctx) <+> show(idndef, ctx) <> show(args, ctx) <> showReturns(returns, ctx) <> - showPresPosts(pres, posts, ctx) <> showBody(showOption(body, ctx), !(returns.isEmpty && pres.isEmpty && posts.isEmpty)) + showAnnotations(annotations) <@@> show(keyword) <+> show(idndef) <> show(args) <> showReturns(returns) <> + showPresPosts(pres, posts) <> showBody(showOption(body), !(returns.isEmpty && pres.isEmpty && posts.isEmpty)) } } case class PMethodReturns(k: PKw.Returns, formalReturns: PGrouped.Paren[PDelimited[PFormalReturnDecl, PSym.Comma]])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(ctx: ReformatterContext): Cont = show(k, ctx) <+> show(formalReturns, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(k) <+> show(formalReturns) } /** @@ -2065,21 +2065,21 @@ case class PAnnotationsPosition(annotations: Seq[PAnnotation], pos: (FilePositio case class PAnnotation(at: PSym.At, key: PRawString, values: PGrouped.Paren[PDelimited[PStringLiteral, PSym.Comma]])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { override def pretty: String = super.pretty + "\n" - override def reformat(ctx: ReformatterContext): Cont = show(at, ctx) <> show(key, ctx) <> show(values, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(at) <> show(key) <> show(values) } // Any unenclosed string (e.g. `hello`) case class PRawString(str: String)(val pos: (Position, Position)) extends PNode with PLeaf { override def display: String = str - override def reformat(ctx: ReformatterContext): Cont = text(str) + override def reformat(implicit ctx: ReformatterContext): Cont = text(str) } // Any enclosed string (e.g. `"hello"`) case class PStringLiteral(grouped: PGrouped[_, PRawString])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { def str: String = grouped.inner.str - override def reformat(ctx: ReformatterContext): Cont = show(grouped, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(grouped) } trait PExtender extends PNode { @@ -2102,19 +2102,19 @@ trait PExtender extends PNode { trait Trivia extends Reformattable case class POther() extends Trivia { - override def reformat(ctx: ReformatterContext): Cont = "" + override def reformat(implicit ctx: ReformatterContext): Cont = "" } case class PSpace() extends Trivia { - override def reformat(ctx: ReformatterContext): Cont = space + override def reformat(implicit ctx: ReformatterContext): Cont = space } case class PNewLine() extends Trivia { - override def reformat(ctx: ReformatterContext): Cont = linebreak + override def reformat(implicit ctx: ReformatterContext): Cont = linebreak } case class PComment(content: String, block: Boolean) extends Trivia { - override def reformat(ctx: ReformatterContext): Cont = if (block) { + override def reformat(implicit ctx: ReformatterContext): Cont = if (block) { text("/*") <> content <> text("*/") } else { text("//") <> text(content) diff --git a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala index 9a47bf298..ef0ef3a03 100644 --- a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala +++ b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala @@ -24,7 +24,7 @@ case class PReserved[+T <: PReservedString](rs: T)(val pos: (Position, Position) override def display = rs.display def token = rs.token - override def reformat(ctx: ReformatterContext): Cont = text(token) + override def reformat(implicit ctx: ReformatterContext): Cont = text(token) } object PReserved { def implied[T <: PReservedString](rs: T): PReserved[T] = PReserved(rs)(NoPosition, NoPosition) @@ -38,18 +38,18 @@ case class PGrouped[G <: PSym.Group, +T](l: PReserved[G#L], inner: T, r: PReserv s"${l.pretty}${iPretty}${r.pretty}" } - override def reformat(ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): Cont = { if (l.rs.isInstanceOf[Brace]) { - val left = show(l, ctx); - val inner_ = showAny(inner, ctx); - val right = show(r, ctx); + val left = show(l); + val inner_ = showAny(inner); + val right = show(r); if (inner_ == nil) { left <> right } else { left <> nest(defaultIndent, line <> inner_) <> line <> right } } else { - show(l, ctx) <> nest(defaultIndent, showAny(inner, ctx)) <> show(r, ctx) + show(l) <> nest(defaultIndent, showAny(inner)) <> show(r) } } } @@ -105,7 +105,7 @@ class PDelimited[+T, +D]( override def hashCode(): Int = viper.silver.utility.Common.generateHashCode(first, inner, end) override def toString(): String = s"PDelimited($first,$inner,$end)" - override def reformat(ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): Cont = { // println(s"PDelimited"); // println(s"---------------------------"); // println(s"first: ${first}"); @@ -118,9 +118,9 @@ class PDelimited[+T, +D]( case _ => line }; - showAny(first, ctx) <@@@> - inner.foldLeft(nil)((acc, b) => acc <@@@> showAny(b._1, ctx) <@@@> separator <@@@> showAny(b._2, ctx)) <@@@> - showAny(end, ctx) + showAny(first) <@@@> + inner.foldLeft(nil)((acc, b) => acc <@@@> showAny(b._1) <@@@> separator <@@@> showAny(b._2)) <@@@> + showAny(end) } } @@ -169,7 +169,7 @@ sealed trait PKeywordIf extends PKeywordStmt abstract class PKw(val keyword: String) extends PKeyword with Reformattable { - override def reformat(ctx: ReformatterContext): Cont = text(keyword) + override def reformat(implicit ctx: ReformatterContext): Cont = text(keyword) } object PKw { @@ -308,7 +308,7 @@ trait PSymbol extends PReservedString with Reformattable { def symbol: String override def token = symbol - override def reformat(ctx: ReformatterContext): Cont = text(symbol) + override def reformat(implicit ctx: ReformatterContext): Cont = text(symbol) } trait PSymbolLang extends PSymbol diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 41a968c76..4be89277d 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -7,15 +7,12 @@ import viper.silver.ast.{HasLineColumn, LineColumnPosition, Position} import viper.silver.parser.FastParserCompanion.programTrivia import viper.silver.plugin.standard.adt.PAdtConstructor -import scala.:: -import scala.util.control.Breaks.{break, breakable} - trait Reformattable extends FastPrettyPrinterBase { - def reformat(ctx: ReformatterContext): Cont + def reformat(implicit ctx: ReformatterContext): Cont } trait ReformattableExpression extends FastPrettyPrinterBase { - def reformatExp(ctx: ReformatterContext): Cont + def reformatExp(implicit ctx: ReformatterContext): Cont } class ReformatterContext(val program: String, val offsets: Seq[Int], val posMap: Map[Position, Position]) { @@ -70,40 +67,40 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { } } - val ctx = new ReformatterContext(p.rawProgram, p.offsets, positions) - super.pretty(defaultWidth, show(p, ctx)) + implicit val ctx = new ReformatterContext(p.rawProgram, p.offsets, positions) + super.pretty(defaultWidth, show(p)) } - def showOption[T <: Any](n: Option[T], ctx: ReformatterContext): Cont = { + def showOption[T <: Any](n: Option[T])(implicit ctx: ReformatterContext): Cont = { n match { - case Some(r) => showAny(r, ctx) + case Some(r) => showAny(r) case None => nil } } - def showAnnotations(annotations: Seq[PAnnotation], ctx: ReformatterContext): Cont = { + def showAnnotations(annotations: Seq[PAnnotation])(implicit ctx: ReformatterContext): Cont = { if (annotations.isEmpty) { nil } else { - annotations.map(show(_, ctx)).foldLeft(nil)((acc, n) => acc <@@> n) + annotations.map(show).foldLeft(nil)((acc, n) => acc <@@> n) } } - def showReturns(returns: Option[PMethodReturns], ctx: ReformatterContext): Cont = { - returns.map(a => nil <+> show(a, ctx)).getOrElse(nil) + def showReturns(returns: Option[PMethodReturns])(implicit ctx: ReformatterContext): Cont = { + returns.map(a => nil <+> show(a)).getOrElse(nil) } - def showPresPosts(pres: PDelimited[_, _], posts: PDelimited[_, _], ctx: ReformatterContext): Cont = { + def showPresPosts(pres: PDelimited[_, _], posts: PDelimited[_, _])(implicit ctx: ReformatterContext): Cont = { nest(defaultIndent, (if (pres.isEmpty) nil - else line <> show(pres, ctx)) <> + else line <> show(pres)) <> (if (posts.isEmpty) nil - else line <> show(posts, ctx) + else line <> show(posts) ) ) } - def showInvs(invs: PDelimited[_, _], ctx: ReformatterContext): Cont = { - nest(defaultIndent, (if (invs.isEmpty) nil else line <> show(invs, ctx))) + def showInvs(invs: PDelimited[_, _])(implicit ctx: ReformatterContext): Cont = { + nest(defaultIndent, (if (invs.isEmpty) nil else line <> show(invs))) } def showBody(body: Cont, newline: Boolean): Cont = { @@ -114,7 +111,7 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { } } - def show(r: Reformattable, ctx: ReformatterContext): Cont = { + def show(r: Reformattable)(implicit ctx: ReformatterContext): Cont = { val trivia = r match { case p: PLeaf => { val trivia = ctx.posMap.get(p.pos._2).map(end => { @@ -170,17 +167,17 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { r.reformat(ctx) <> trivia } - def showAny(n: Any, ctx: ReformatterContext): Cont = { + def showAny(n: Any)(implicit ctx: ReformatterContext): Cont = { n match { - case p: Reformattable => show(p, ctx) - case p: Option[Any] => showOption(p, ctx) - case p: Seq[Any] => showSeq(p, ctx) - case p: Right[Any, Any] => showAny(p.value, ctx) - case p: Left[Any, Any] => showAny(p.value, ctx) + case p: Reformattable => show(p) + case p: Option[Any] => showOption(p) + case p: Seq[Any] => showSeq(p) + case p: Right[Any, Any] => showAny(p.value) + case p: Left[Any, Any] => showAny(p.value) } } - def showSeq(l: Seq[Any], ctx: ReformatterContext): Cont = { + def showSeq(l: Seq[Any])(implicit ctx: ReformatterContext): Cont = { if (l.isEmpty) { nil } else { @@ -188,7 +185,7 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { case _: PAdtConstructor => linebreak case _ => linebreak } - l.map(showAny(_, ctx)).reduce(_ <> sep <> _) + l.map(showAny(_)).reduce(_ <> sep <> _) } } } \ No newline at end of file diff --git a/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala b/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala index f6b8412fc..14bd9c7af 100644 --- a/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala +++ b/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala @@ -94,7 +94,7 @@ trait ParserPluginTemplate { override def translateMember(t: Translator): Member = ??? override def translateMemberSignature(t: Translator): Member = super.translateMemberSignature(t) override def pretty = "" - override def reformat(ctx: ReformatterContext): Cont = "" + override def reformat(implicit ctx: ReformatterContext): Cont = "" } case class PExampleStmt()(val pos: (Position, Position)) extends PExtender with PStmt{ @@ -103,7 +103,7 @@ trait ParserPluginTemplate { // The overridden function to translate this node to a corresponding Ast node override def translateStmt(t: Translator): Stmt = super.translateStmt(t) - override def reformat(ctx: ReformatterContext): Cont = "" + override def reformat(implicit ctx: ReformatterContext): Cont = "" } case class PExampleExp()(val pos: (Position, Position)) extends PExtender with PExp{ @@ -115,7 +115,7 @@ trait ParserPluginTemplate { override def typecheck(t: TypeChecker, n: NameAnalyser): Option[Seq[String]] = super.typecheck(t, n) // The translator function to translate the PAst node corresponding to the Ast node override def translateExp(t: Translator): Exp = super.translateExp(t) - override def reformatExp(ctx: ReformatterContext): Cont = "" + override def reformatExp(implicit ctx: ReformatterContext): Cont = "" } /** diff --git a/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala index 7c6fb43a6..33ea94178 100644 --- a/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala @@ -78,8 +78,8 @@ case class PAdt(annotations: Seq[PAnnotation], adt: PReserved[PAdtKeyword.type], adtType } - override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> show(adt, ctx) <+> - show(idndef, ctx) <> showOption(typVars, ctx) <+> show(c, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> show(adt) <+> + show(idndef) <> showOption(typVars) <+> show(c) } object PAdt { @@ -102,8 +102,8 @@ case class PAdtSeq[T <: PNode](seq: PGrouped[PSym.Brace, Seq[T]])(val pos: (Posi def inner: Seq[T] = seq.inner override def pretty = s"${seq.l.pretty}\n ${seq.inner.map(_.pretty).mkString("\n ")}\n${seq.r.pretty}" - override def reformat(ctx: ReformatterContext): Cont = { - show(seq, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = { + show(seq) } } @@ -112,8 +112,8 @@ case class PAdtFieldDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (P def constructor: PAdtConstructor = getAncestor[PAdtConstructor].get def annotations: Seq[PAnnotation] = Nil - override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <> - show(c, ctx) <+> show(typ, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <> + show(c) <+> show(typ) } object PAdtFieldDecl { def apply(d: PIdnTypeBinding): PAdtFieldDecl = PAdtFieldDecl(d.idndef, d.c, d.typ)(d.pos) @@ -149,8 +149,8 @@ case class PAdtConstructor(annotations: Seq[PAnnotation], idndef: PIdnDef, args: override def c = PReserved.implied(PSym.Colon) override def body = None - override def reformat(ctx: ReformatterContext): Cont = showAnnotations(annotations, ctx) <@@> - show(idndef, ctx) <> show(args, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> + show(idndef) <> show(args) } object PAdtConstructor { @@ -180,7 +180,7 @@ case class PAdtDeriving(k: PReserved[PDerivesKeyword.type], derivingInfos: PAdtS None } - override def reformat(ctx: ReformatterContext): Cont = show(k, ctx) <+> show(derivingInfos, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(k) <+> show(derivingInfos) } case class PAdtWithout(k: PReserved[PWithoutKeyword.type], blockList: PDelimited[PIdnRef[PAdtFieldDecl], PSym.Comma])(val pos: (Position, Position)) extends PExtender with PPrettySubnodes with PAdtChild { @@ -194,7 +194,7 @@ case class PAdtWithout(k: PReserved[PWithoutKeyword.type], blockList: PDelimited None } - override def reformat(ctx: ReformatterContext): Cont = show(k, ctx) <+> show(blockList, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(k) <+> show(blockList) } case class PAdtDerivingInfo(idndef: PIdnDef, param: Option[PGrouped[PSym.Bracket, PType]], without: Option[PAdtWithout])(val pos: (Position, Position)) extends PExtender with PPrettySubnodes { @@ -205,7 +205,7 @@ case class PAdtDerivingInfo(idndef: PIdnDef, param: Option[PGrouped[PSym.Bracket None } - override def reformat(ctx: ReformatterContext): Cont = show(idndef, ctx) <+> showOption(param, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <+> showOption(param) } case class PAdtType(adt: PIdnRef[PAdt], args: Option[PDelimited.Comma[PSym.Bracket, PType]]) @@ -274,7 +274,7 @@ case class PAdtType(adt: PIdnRef[PAdt], args: Option[PDelimited.Comma[PSym.Brack if (s.length == 0 && args.isEmpty) this else copy(args = Some(args.get.update(s)))(pos) override def copyExtraVars(from: Any): Unit = this.kind = from.asInstanceOf[PAdtType].kind - override def reformat(ctx: ReformatterContext): Cont = show(adt, ctx) <> showOption(args, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(adt) <> showOption(args) } object PAdtTypeKinds { @@ -479,8 +479,8 @@ case class PConstructorCall(idnref: PIdnRef[PAdtConstructor], callArgs: PDelimit } } - override def reformatExp(ctx: ReformatterContext): Cont = show(idnref, ctx) <> - show(callArgs, ctx) <> showOption(typeAnnotated, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(idnref) <> + show(callArgs) <> showOption(typeAnnotated) } case class PDestructorCall(rcv: PExp, dot: PReserved[PDiscDot.type], idnref: PIdnRef[PAdtFieldDecl]) @@ -514,7 +514,7 @@ case class PDestructorCall(rcv: PExp, dot: PReserved[PDiscDot.type], idnref: PId } } - override def reformatExp(ctx: ReformatterContext): Cont = show(rcv, ctx) <> show(dot, ctx) <> show(idnref, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(rcv) <> show(dot) <> show(idnref) } case object PIsKeyword extends PKwOp("is") { @@ -552,5 +552,5 @@ case class PDiscriminatorCall(rcv: PExp, dot: PReserved[PDiscDot.type], is: PRes } } - override def reformatExp(ctx: ReformatterContext): Cont = show(rcv, ctx) <> show(dot, ctx) <> show(is, ctx) <> show(idnref, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(rcv) <> show(dot) <> show(is) <> show(idnref) } \ No newline at end of file diff --git a/src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePASTExtension.scala index bcf0c5c40..6176844f9 100644 --- a/src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePASTExtension.scala @@ -45,6 +45,6 @@ case class PPredicateInstance(m: PReserved[PMarkerSymbol.type], idnuse: PIdnRef[ PredicateInstance(idnuse.name, args.inner.toSeq map t.exp)(t.liftPos(this)) } - override def reformatExp(ctx: ReformatterContext): Cont = show(m, ctx) <> - show(idnuse, ctx) <> show(args, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(m) <> + show(idnuse) <> show(args) } diff --git a/src/main/scala/viper/silver/plugin/standard/refute/RefutePASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/refute/RefutePASTExtension.scala index fb6a258c4..b7b394f00 100644 --- a/src/main/scala/viper/silver/plugin/standard/refute/RefutePASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/refute/RefutePASTExtension.scala @@ -23,5 +23,5 @@ case class PRefute(refute: PReserved[PRefuteKeyword.type], e: PExp)(val pos: (Po override def translateStmt(t: Translator): Stmt = Refute(t.exp(e))(t.liftPos(this)) - override def reformat(ctx: ReformatterContext): Cont = show(refute, ctx) <+> show(e, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(refute) <+> show(e) } diff --git a/src/main/scala/viper/silver/plugin/standard/smoke/UnreachablePASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/smoke/UnreachablePASTExtension.scala index 96d760b42..bf0a3b534 100644 --- a/src/main/scala/viper/silver/plugin/standard/smoke/UnreachablePASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/smoke/UnreachablePASTExtension.scala @@ -20,5 +20,5 @@ case class PUnreachable(kw: PReserved[PUnreachableKeyword.type])(val pos: (Posit override def translateStmt(t: Translator): Stmt = Unreachable()(t.liftPos(this)) - override def reformat(ctx: ReformatterContext): Cont = show(kw, ctx) + override def reformat(implicit ctx: ReformatterContext): Cont = show(kw) } diff --git a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala index e5b44cbf4..af53c9599 100644 --- a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala @@ -44,8 +44,8 @@ case class PDecreasesTuple(tuple: PDelimited[PExp, PSym.Comma], condition: Optio DecreasesTuple(tuple.toSeq map t.exp, condition map (_._2) map t.exp)(t.liftPos(this)) } - override def reformatExp(ctx: ReformatterContext): Cont = - show(tuple, ctx) <> condition.map((e) => space <> show(e._1, ctx) <+> show(e._2, ctx)).getOrElse(nil) + override def reformatExp(implicit ctx: ReformatterContext): Cont = + show(tuple) <> condition.map((e) => space <> show(e._1) <+> show(e._2)).getOrElse(nil) } case class PDecreasesWildcard(wildcard: PReserved[PWildcardSym.type], condition: Option[(PReserved[PIfKeyword.type], PExp)] = None)(val pos: (Position, Position)) extends PDecreasesClause { @@ -60,8 +60,8 @@ case class PDecreasesWildcard(wildcard: PReserved[PWildcardSym.type], condition: DecreasesWildcard(condition map (_._2) map t.exp)(t.liftPos(this)) } - override def reformatExp(ctx: ReformatterContext): Cont = show(wildcard, ctx) <+> - condition.map((e) => show(e._1, ctx) <+> show(e._2, ctx)).getOrElse(nil) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(wildcard) <+> + condition.map((e) => show(e._1) <+> show(e._2)).getOrElse(nil) } case class PDecreasesStar(star: PSym.Star)(val pos: (Position, Position)) extends PDecreasesClause { @@ -74,6 +74,6 @@ case class PDecreasesStar(star: PSym.Star)(val pos: (Position, Position)) extend DecreasesStar()(t.liftPos(this)) } - override def reformatExp(ctx: ReformatterContext): Cont = show(star, ctx) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(star) } From 8d49529203d81e51da6ea78e959202e1c7b16fe0 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Tue, 19 Nov 2024 13:30:21 +0100 Subject: [PATCH 12/47] Remove unused method --- src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala index 85d22e881..92c88c12e 100644 --- a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala +++ b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala @@ -359,9 +359,6 @@ trait FastPrettyPrinterBase extends PrettyPrintPrimitives { def linebreak : Cont = line ("\n") - def dlinebreak : Cont = - line ("\n\n") - implicit class ContOps(dl: Cont) { def <>(dr: Cont) : Cont = From 7e9dc9c4a4ba7931c17a27ebe4ae9921e0a96f3a Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Tue, 19 Nov 2024 13:44:22 +0100 Subject: [PATCH 13/47] roll back to looking back for trivia --- .../viper/silver/parser/ReformatPrettyPrinter.scala | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 4be89277d..3c823991d 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -59,11 +59,11 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { } } val leavePositions = collectLeavePositions(p) - var positions: Map[ast.Position, ast.Position] = Map(LineColumnPosition(1, 1) -> leavePositions.headOption.map(p => p._1).getOrElse(LineColumnPosition(1, 1))) + var positions: Map[ast.Position, ast.Position] = Map(leavePositions.headOption.map(p => p._1).getOrElse(LineColumnPosition(1, 1)) -> LineColumnPosition(1, 1)) if (leavePositions.length > 1) { leavePositions.sliding(2).foreach { - case Seq(a, b) => positions += (a._2 -> b._1) + case Seq(a, b) => positions += (b._1 -> a._2) } } @@ -114,11 +114,9 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { def show(r: Reformattable)(implicit ctx: ReformatterContext): Cont = { val trivia = r match { case p: PLeaf => { - val trivia = ctx.posMap.get(p.pos._2).map(end => { - println(s"${p.pos._2}, ${end}"); - ctx.getTrivia(p.pos._2, end) + val trivia = ctx.posMap.get(p.pos._1).map(end => { + ctx.getTrivia(end, p.pos._2) }).getOrElse({ - Seq() }); @@ -164,7 +162,7 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { case _ => nil } - r.reformat(ctx) <> trivia + trivia <> r.reformat(ctx) } def showAny(n: Any)(implicit ctx: ReformatterContext): Cont = { From 7c4c42a3c0a241448bc4586face27bd8d81430e6 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 20 Nov 2024 14:32:50 +0100 Subject: [PATCH 14/47] Fix issue with missing indent after comment --- .../scala/viper/silver/parser/ParseAst.scala | 4 +- .../silver/parser/ReformatPrettyPrinter.scala | 58 ++++++------------- 2 files changed, 20 insertions(+), 42 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 83f94509f..1cc487ad3 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -2115,8 +2115,8 @@ case class PNewLine() extends Trivia { case class PComment(content: String, block: Boolean) extends Trivia { override def reformat(implicit ctx: ReformatterContext): Cont = if (block) { - text("/*") <> content <> text("*/") + text("/*") <> content <> text("*/") <> linebreak } else { - text("//") <> text(content) + text("//") <> text(content) <> linebreak } } \ No newline at end of file diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 3c823991d..b83034f87 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -15,29 +15,32 @@ trait ReformattableExpression extends FastPrettyPrinterBase { def reformatExp(implicit ctx: ReformatterContext): Cont } -class ReformatterContext(val program: String, val offsets: Seq[Int], val posMap: Map[Position, Position]) { +class ReformatterContext(val program: String, val offsets: Seq[Int]) { + var currentOffset: Int = 0 + def getByteOffset(p: HasLineColumn): Int = { val row = offsets(p.line - 1); row + p.column - 1 } - def getTrivia(start: ast.Position, end: ast.Position): Seq[Trivia] = { - (start, end) match { - case (p: HasLineColumn, q: HasLineColumn) => { + def getTrivia(pos: (ast.Position, ast.Position)): Seq[Trivia] = { + pos._1 match { + case p: HasLineColumn => { val p_offset = getByteOffset(p); - val q_offset = getByteOffset(q); - getTriviaByByteOffset(p_offset, q_offset) + getTriviaByByteOffset(p_offset) } case _ => Seq() } } - def getTriviaByByteOffset(startOffset: Int, endOffset: Int): Seq[Trivia] = { - if (startOffset < endOffset) { - val str = program.substring(startOffset, endOffset); + def getTriviaByByteOffset(offset: Int): Seq[Trivia] = { + if (currentOffset <= offset) { + val str = program.substring(currentOffset, offset); + this.currentOffset = offset; fastparse.parse(str, programTrivia(_)) match { case Parsed.Success(value, _) => { + println(s"Length: ${value.length}") value } case _: Parsed.Failure => Seq() @@ -52,22 +55,7 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { override val defaultIndent = 4 def reformatProgram(p: PProgram): String = { - def collectLeavePositions(p: PNode): Seq[(ast.Position, ast.Position)] = { - p match { - case p: PLeaf => Seq(p.pos) - case _ => p.subnodes.flatMap(collectLeavePositions) - } - } - val leavePositions = collectLeavePositions(p) - var positions: Map[ast.Position, ast.Position] = Map(leavePositions.headOption.map(p => p._1).getOrElse(LineColumnPosition(1, 1)) -> LineColumnPosition(1, 1)) - - if (leavePositions.length > 1) { - leavePositions.sliding(2).foreach { - case Seq(a, b) => positions += (b._1 -> a._2) - } - } - - implicit val ctx = new ReformatterContext(p.rawProgram, p.offsets, positions) + implicit val ctx = new ReformatterContext(p.rawProgram, p.offsets) super.pretty(defaultWidth, show(p)) } @@ -92,9 +80,9 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { def showPresPosts(pres: PDelimited[_, _], posts: PDelimited[_, _])(implicit ctx: ReformatterContext): Cont = { nest(defaultIndent, (if (pres.isEmpty) nil - else line <> show(pres)) <> + else linebreak <> show(pres)) <> (if (posts.isEmpty) nil - else line <> show(posts) + else linebreak <> show(posts) ) ) } @@ -114,13 +102,7 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { def show(r: Reformattable)(implicit ctx: ReformatterContext): Cont = { val trivia = r match { case p: PLeaf => { - val trivia = ctx.posMap.get(p.pos._1).map(end => { - ctx.getTrivia(end, p.pos._2) - }).getOrElse({ - Seq() - }); - - println(s"Trivia: ${trivia}"); + val trivia = ctx.getTrivia(p.pos); var reformatted = nil var newlines = 0; @@ -129,8 +111,8 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { for (t <- trivia) { t match { case p: PComment => { - val lw = if (newlines > 0) linebreak else if(spaces > 0) space else nil - reformatted = reformatted <> lw <> group(p.reformat(ctx)) + val lw = if (newlines > 1) linebreak else nil + reformatted = reformatted <> lw <> p.reformat(ctx) newlines = 0 spaces = 0 } @@ -140,10 +122,6 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { } } - if (newlines > 0) { - reformatted = reformatted <> linebreak - } - val hasComment = trivia exists { case _: PComment => true case _ => false From 96b6e97b7fd4153b8401bc5f86651e2881ea98db Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 20 Nov 2024 14:39:57 +0100 Subject: [PATCH 15/47] Everything works as initially --- src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index b83034f87..8a52dd96e 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -40,7 +40,6 @@ class ReformatterContext(val program: String, val offsets: Seq[Int]) { fastparse.parse(str, programTrivia(_)) match { case Parsed.Success(value, _) => { - println(s"Length: ${value.length}") value } case _: Parsed.Failure => Seq() @@ -140,7 +139,7 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { case _ => nil } - trivia <> r.reformat(ctx) + trivia <@@@> r.reformat(ctx) } def showAny(n: Any)(implicit ctx: ReformatterContext): Cont = { From e41dba26b0cc89652e620568d8326f981c1c9d4f Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 20 Nov 2024 14:46:17 +0100 Subject: [PATCH 16/47] Simplify code a bit --- .../scala/viper/silver/parser/ReformatPrettyPrinter.scala | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 8a52dd96e..4c4ed0621 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -156,11 +156,7 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { if (l.isEmpty) { nil } else { - val sep = l.head match { - case _: PAdtConstructor => linebreak - case _ => linebreak - } - l.map(showAny(_)).reduce(_ <> sep <> _) + l.map(showAny(_)).reduce(_ <> linebreak <> _) } } } \ No newline at end of file From 52627f385c0aac02eafa89f95030ed313b7c7a51 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 20 Nov 2024 20:41:55 +0100 Subject: [PATCH 17/47] next attempt --- .../silver/ast/pretty/PrettyPrinter.scala | 4 +- .../scala/viper/silver/parser/ParseAst.scala | 6 +- .../silver/parser/ReformatPrettyPrinter.scala | 55 +++++++++++++++---- 3 files changed, 50 insertions(+), 15 deletions(-) diff --git a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala index 92c88c12e..989cca495 100644 --- a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala +++ b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala @@ -346,8 +346,6 @@ trait FastPrettyPrinterBase extends PrettyPrintPrimitives { def parens (d : Cont) : Cont = char ('(') <> d <> char (')') - - def brackets (d : Cont) : Cont = char ('[') <> d <> char (']') @@ -355,6 +353,8 @@ trait FastPrettyPrinterBase extends PrettyPrintPrimitives { def space : Cont = char (' ') + def dlinebreak : Cont = + linebreak <> linebreak def linebreak : Cont = line ("\n") diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 1cc487ad3..f2f9c9b3d 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -1883,7 +1883,7 @@ case class PProgram(imported: Seq[PProgram], members: Seq[PMember])(val pos: (Po override def reformat(implicit ctx: ReformatterContext): Cont = { println(s"whole program ${this.members}"); - members.map(show(_)).foldLeft(nil)((acc, n) => acc <@@> n) + members.map(show(_, linebreak)).foldLeft(nil)((acc, n) => acc <@@> n) // Don't forget comments that appear after any nodes! // formatTrivia(ctx.getTriviaByByteOffset(rawProgram.length)) } @@ -2115,8 +2115,8 @@ case class PNewLine() extends Trivia { case class PComment(content: String, block: Boolean) extends Trivia { override def reformat(implicit ctx: ReformatterContext): Cont = if (block) { - text("/*") <> content <> text("*/") <> linebreak + text("/*") <> content <> text("*/") } else { - text("//") <> text(content) <> linebreak + text("//") <> text(content) } } \ No newline at end of file diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 4c4ed0621..668254092 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -69,7 +69,7 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { if (annotations.isEmpty) { nil } else { - annotations.map(show).foldLeft(nil)((acc, n) => acc <@@> n) + annotations.map(show(_)).foldLeft(nil)((acc, n) => acc <@@> n) } } @@ -98,19 +98,38 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { } } - def show(r: Reformattable)(implicit ctx: ReformatterContext): Cont = { + def show(r: Reformattable, sep: Cont = nil)(implicit ctx: ReformatterContext): Cont = { val trivia = r match { case p: PLeaf => { val trivia = ctx.getTrivia(p.pos); var reformatted = nil + var leadingNewlines = 0; + var leadingSpaces = 0; var newlines = 0; var spaces = 0; + var hasComment = false + + def getSep(newlines: Int, spaces: Int): Cont = { + if (newlines > 1) dlinebreak + else if (newlines > 0) linebreak + else if (spaces > 0) space + else nil + } + + println(trivia); for (t <- trivia) { t match { case p: PComment => { - val lw = if (newlines > 1) linebreak else nil + val lw = if (!hasComment) { + leadingNewlines = newlines; + leadingSpaces = spaces; + hasComment = true; + nil + } else { + getSep(newlines, spaces) + } reformatted = reformatted <> lw <> p.reformat(ctx) newlines = 0 spaces = 0 @@ -121,18 +140,34 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { } } - val hasComment = trivia exists { - case _: PComment => true - case _ => false - } + val trailingNewlines = newlines; + val trailingSpaces = spaces; if (hasComment) { + val leadingSep = getSep(leadingNewlines, leadingSpaces) + val trailingSep = getSep(trailingNewlines, trailingSpaces) + val Space: Cont = space; + val Linebreak: Cont = linebreak; + val Line: Cont = line; + + sep match { + case Space => (if (leadingSep == nil) space else leadingSep) <> reformatted <> + (if (trailingSep == nil) space else trailingSep) + case Linebreak => leadingSep <> reformatted <> (if (trailingSep == dlinebreak) dlinebreak else linebreak) + case Line => leadingSep <> reformatted <> (if (trailingSep == dlinebreak) dlinebreak else line) + // `nil` and others + case _ => leadingSep <> reformatted <> trailingSep + } + reformatted } else { - if (newlines > 1) { - linebreak + println(s"${newlines}"); + println(s"${sep == linebreak}"); + if (newlines > 1 && sep == linebreak) { + println("double break!"); + dlinebreak } else { - nil + sep } } }; From 0c694936fcac00b2b047fc977ec1245d2a9f3c43 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 20 Nov 2024 22:02:02 +0100 Subject: [PATCH 18/47] Good progress towards better formatting! --- .../scala/viper/silver/parser/ParseAst.scala | 21 +- .../viper/silver/parser/ParseAstKeyword.scala | 8 +- .../silver/parser/ReformatPrettyPrinter.scala | 181 ++++++++++-------- 3 files changed, 117 insertions(+), 93 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index f2f9c9b3d..4a9be0352 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -8,6 +8,7 @@ package viper.silver.parser import viper.silver.ast +import viper.silver.ast.pretty.FastPrettyPrinterBase import viper.silver.ast.{FilePosition, HasLineColumn, Position} import viper.silver.parser.ReformatPrettyPrinter.{show, showAnnotations, showAny, showBody, showInvs, showOption, showPresPosts, showReturns, showSeq} @@ -1882,10 +1883,10 @@ case class PProgram(imported: Seq[PProgram], members: Seq[PMember])(val pos: (Po } override def reformat(implicit ctx: ReformatterContext): Cont = { - println(s"whole program ${this.members}"); - members.map(show(_, linebreak)).foldLeft(nil)((acc, n) => acc <@@> n) - // Don't forget comments that appear after any nodes! -// formatTrivia(ctx.getTriviaByByteOffset(rawProgram.length)) + if (members.isEmpty) + nil + else + members.zipWithIndex.map(e => show(e._1, if (e._2 == 0) SNil() else SLinebreak())).reduce((acc, n) => acc <> n) } // Pretty print members in a specific order @@ -2099,22 +2100,24 @@ trait PExtender extends PNode { } // Trivia (comments, whitespaces) -trait Trivia extends Reformattable +trait Trivia extends FastPrettyPrinterBase { + def display: Cont +} case class POther() extends Trivia { - override def reformat(implicit ctx: ReformatterContext): Cont = "" + override def display: Cont = text("") } case class PSpace() extends Trivia { - override def reformat(implicit ctx: ReformatterContext): Cont = space + override def display: Cont = space } case class PNewLine() extends Trivia { - override def reformat(implicit ctx: ReformatterContext): Cont = linebreak + override def display: Cont = linebreak } case class PComment(content: String, block: Boolean) extends Trivia { - override def reformat(implicit ctx: ReformatterContext): Cont = if (block) { + def display: Cont = if (block) { text("/*") <> content <> text("*/") } else { text("//") <> text(content) diff --git a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala index ef0ef3a03..8078dfc37 100644 --- a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala +++ b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala @@ -168,8 +168,8 @@ sealed trait PKeywordAtom sealed trait PKeywordIf extends PKeywordStmt -abstract class PKw(val keyword: String) extends PKeyword with Reformattable { - override def reformat(implicit ctx: ReformatterContext): Cont = text(keyword) +abstract class PKw(val keyword: String) extends PKeyword { +// override def reformat(implicit ctx: ReformatterContext): Cont = text(keyword) } object PKw { @@ -304,11 +304,9 @@ object PKw { } /** Anything that is composed of /![a-zA-Z]/ characters. */ -trait PSymbol extends PReservedString with Reformattable { +trait PSymbol extends PReservedString { def symbol: String override def token = symbol - - override def reformat(implicit ctx: ReformatterContext): Cont = text(symbol) } trait PSymbolLang extends PSymbol diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 668254092..6b7116fd6 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -3,11 +3,31 @@ package viper.silver.parser import fastparse.Parsed import viper.silver.ast import viper.silver.ast.pretty.FastPrettyPrinterBase -import viper.silver.ast.{HasLineColumn, LineColumnPosition, Position} +import viper.silver.ast.{HasLineColumn} import viper.silver.parser.FastParserCompanion.programTrivia -import viper.silver.plugin.standard.adt.PAdtConstructor -trait Reformattable extends FastPrettyPrinterBase { +sealed trait Separator extends FastPrettyPrinterBase { + def doc: Cont +} + +case class SNil() extends Separator { + override def doc: Cont = nil +} +case class SSpace() extends Separator { + override def doc: Cont = space +} +case class SLine() extends Separator { + override def doc: Cont = line +} +case class SLinebreak() extends Separator { + override def doc: Cont = linebreak +} +case class SDLinebreak() extends Separator { + override def doc: Cont = dlinebreak +} + + +trait Reformattable extends FastPrettyPrinterBase with Where { def reformat(implicit ctx: ReformatterContext): Cont } @@ -23,20 +43,26 @@ class ReformatterContext(val program: String, val offsets: Seq[Int]) { row + p.column - 1 } - def getTrivia(pos: (ast.Position, ast.Position)): Seq[Trivia] = { - pos._1 match { - case p: HasLineColumn => { + def getTrivia(pos: (ast.Position, ast.Position), updateOffset: Boolean): Seq[Trivia] = { + (pos._1, pos._2) match { + case (p: HasLineColumn, q: HasLineColumn) => { val p_offset = getByteOffset(p); - getTriviaByByteOffset(p_offset) + val q_offset = getByteOffset(q); + getTriviaByByteOffset(p_offset, if (updateOffset) Some(q_offset) else None) } case _ => Seq() } } - def getTriviaByByteOffset(offset: Int): Seq[Trivia] = { + def getTriviaByByteOffset(offset: Int, updateOffset: Option[Int]): Seq[Trivia] = { if (currentOffset <= offset) { val str = program.substring(currentOffset, offset); - this.currentOffset = offset; + currentOffset = currentOffset.max(offset); + + updateOffset match { + case Some(o) => currentOffset = o + case _ => + } fastparse.parse(str, programTrivia(_)) match { case Parsed.Success(value, _) => { @@ -98,83 +124,80 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { } } - def show(r: Reformattable, sep: Cont = nil)(implicit ctx: ReformatterContext): Cont = { - val trivia = r match { - case p: PLeaf => { - val trivia = ctx.getTrivia(p.pos); - - var reformatted = nil - var leadingNewlines = 0; - var leadingSpaces = 0; - var newlines = 0; - var spaces = 0; - var hasComment = false - - def getSep(newlines: Int, spaces: Int): Cont = { - if (newlines > 1) dlinebreak - else if (newlines > 0) linebreak - else if (spaces > 0) space - else nil - } + def show(r: Reformattable, sep: Separator = SNil())(implicit ctx: ReformatterContext): Cont = { + val updatePos = r match { + case _: PLeaf => true + case _ => false + } - println(trivia); - - for (t <- trivia) { - t match { - case p: PComment => { - val lw = if (!hasComment) { - leadingNewlines = newlines; - leadingSpaces = spaces; - hasComment = true; - nil - } else { - getSep(newlines, spaces) - } - reformatted = reformatted <> lw <> p.reformat(ctx) - newlines = 0 - spaces = 0 - } - case _: PNewLine => newlines += 1 - case _: PSpace => spaces += 1 - case _ => - } - } + println(s"before: ${sep}"); - val trailingNewlines = newlines; - val trailingSpaces = spaces; - - if (hasComment) { - val leadingSep = getSep(leadingNewlines, leadingSpaces) - val trailingSep = getSep(trailingNewlines, trailingSpaces) - val Space: Cont = space; - val Linebreak: Cont = linebreak; - val Line: Cont = line; - - sep match { - case Space => (if (leadingSep == nil) space else leadingSep) <> reformatted <> - (if (trailingSep == nil) space else trailingSep) - case Linebreak => leadingSep <> reformatted <> (if (trailingSep == dlinebreak) dlinebreak else linebreak) - case Line => leadingSep <> reformatted <> (if (trailingSep == dlinebreak) dlinebreak else line) - // `nil` and others - case _ => leadingSep <> reformatted <> trailingSep - } + val trivia = ctx.getTrivia(r.pos, updatePos); - reformatted - } else { - println(s"${newlines}"); - println(s"${sep == linebreak}"); - if (newlines > 1 && sep == linebreak) { - println("double break!"); - dlinebreak - } else { - sep + var reformatted = nil + var leadingNewlines = 0; + var leadingSpaces = 0; + var newlines = 0; + var spaces = 0; + var hasComment = false + + def getSep(newlines: Int, spaces: Int): Separator = { + if (newlines > 1) SDLinebreak() + else if (newlines > 0) SLinebreak() + else if (spaces > 0) SSpace() + else SNil() + } + + println(trivia); + + for (t <- trivia) { + t match { + case p: PComment => { + val lw = if (!hasComment) { + leadingNewlines = newlines; + leadingSpaces = spaces; + hasComment = true; + nil + } else { + getSep(newlines, spaces).doc } + reformatted = reformatted <> lw <> p.display + newlines = 0 + spaces = 0 } - }; - case _ => nil + case _: PNewLine => newlines += 1 + case _: PSpace => spaces += 1 + case _ => + } + } + + val trailingNewlines = newlines; + val trailingSpaces = spaces; + + val formattedTrivia = if (hasComment) { + val leadingSep = getSep(leadingNewlines, leadingSpaces) + val trailingSep = getSep(trailingNewlines, trailingSpaces) + + sep match { + case _: SSpace => (if (leadingSep == SNil()) space else leadingSep.doc) <> reformatted <> + (if (trailingSep == SNil()) space else trailingSep.doc) + case _: SLinebreak => leadingSep.doc <> reformatted <> (if (trailingSep == SDLinebreak()) dlinebreak else linebreak) + case _: SLine => leadingSep.doc <> reformatted <> (if (trailingSep == SDLinebreak()) dlinebreak else line) + // `nil` and others + case _ => leadingSep.doc <> reformatted <> trailingSep.doc + } + } else { + println(s"${newlines}"); + println(s"after: ${sep == linebreak}"); + if (newlines > 1 && sep == SLinebreak()) { + println("double break!"); + dlinebreak + } else { + sep.doc + } } - trivia <@@@> r.reformat(ctx) + formattedTrivia <@@@> r.reformat(ctx) } def showAny(n: Any)(implicit ctx: ReformatterContext): Cont = { From d6ff15768f8776d2fc14f2af7923295ed36c759d Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 20 Nov 2024 22:39:40 +0100 Subject: [PATCH 19/47] Fix spacing in pre and post conditions --- .../viper/silver/parser/ParseAstKeyword.scala | 8 +++--- .../silver/parser/ReformatPrettyPrinter.scala | 26 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala index 8078dfc37..3c1f2bd70 100644 --- a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala +++ b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala @@ -113,13 +113,13 @@ class PDelimited[+T, +D]( // println(s"end: ${end}"); val separator = delimiters.headOption match { - case Some(p: PSym.Comma) => space - case None => nil - case _ => line + case Some(p: PSym.Comma) => SSpace() + case None => SNil() + case _ => SLinebreak() }; showAny(first) <@@@> - inner.foldLeft(nil)((acc, b) => acc <@@@> showAny(b._1) <@@@> separator <@@@> showAny(b._2)) <@@@> + inner.foldLeft(nil)((acc, b) => acc <@@@> showAny(b._1) <@@@> showAny(b._2, separator)) <@@@> showAny(end) } } diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 6b7116fd6..5b50e9897 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -84,9 +84,9 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { super.pretty(defaultWidth, show(p)) } - def showOption[T <: Any](n: Option[T])(implicit ctx: ReformatterContext): Cont = { + def showOption[T <: Any](n: Option[T], sep: Separator = SNil())(implicit ctx: ReformatterContext): Cont = { n match { - case Some(r) => showAny(r) + case Some(r) => showAny(r, sep) case None => nil } } @@ -105,15 +105,15 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { def showPresPosts(pres: PDelimited[_, _], posts: PDelimited[_, _])(implicit ctx: ReformatterContext): Cont = { nest(defaultIndent, (if (pres.isEmpty) nil - else linebreak <> show(pres)) <> + else show(pres, SLinebreak())) <> (if (posts.isEmpty) nil - else linebreak <> show(posts) + else show(posts, SLinebreak()) ) ) } def showInvs(invs: PDelimited[_, _])(implicit ctx: ReformatterContext): Cont = { - nest(defaultIndent, (if (invs.isEmpty) nil else line <> show(invs))) + nest(defaultIndent, (if (invs.isEmpty) nil else show(invs, SLinebreak()))) } def showBody(body: Cont, newline: Boolean): Cont = { @@ -130,7 +130,9 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { case _ => false } - println(s"before: ${sep}"); + println(s"separator: ${sep}"); + println(s"pos: ${r.pos}"); + println(s"node: ${r.getClass}"); val trivia = ctx.getTrivia(r.pos, updatePos); @@ -188,9 +190,7 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { } } else { println(s"${newlines}"); - println(s"after: ${sep == linebreak}"); if (newlines > 1 && sep == SLinebreak()) { - println("double break!"); dlinebreak } else { sep.doc @@ -200,13 +200,13 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { formattedTrivia <@@@> r.reformat(ctx) } - def showAny(n: Any)(implicit ctx: ReformatterContext): Cont = { + def showAny(n: Any, sep: Separator = SNil())(implicit ctx: ReformatterContext): Cont = { n match { - case p: Reformattable => show(p) - case p: Option[Any] => showOption(p) + case p: Reformattable => show(p, sep) + case p: Option[Any] => showOption(p, sep) case p: Seq[Any] => showSeq(p) - case p: Right[Any, Any] => showAny(p.value) - case p: Left[Any, Any] => showAny(p.value) + case p: Right[Any, Any] => showAny(p.value, sep) + case p: Left[Any, Any] => showAny(p.value, sep) } } From 66d93267672e4c22bdaf6f5cbe23462eb284a057 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Thu, 21 Nov 2024 15:28:19 +0100 Subject: [PATCH 20/47] Improve showBody method --- src/main/scala/viper/silver/parser/ParseAst.scala | 14 +++++++------- .../silver/parser/ReformatPrettyPrinter.scala | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 4a9be0352..b73da29c4 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -1684,19 +1684,19 @@ case class PAssign(targets: PDelimited[PExp with PAssignTarget, PSym.Comma], op: sealed trait PIfContinuation extends PStmt case class PIf(keyword: PReserved[PKeywordIf], cond: PGrouped.Paren[PExp], thn: PSeqn, els: Option[PIfContinuation])(val pos: (Position, Position)) extends PStmt with PIfContinuation { override def reformat(implicit ctx: ReformatterContext): Cont = show(keyword) <+> show(cond) <> - showBody(show(thn), false) <+@> showBody(showOption(els), false) + showBody(thn, false) <> els.map(showBody(_, false)).getOrElse(nil) } case class PElse(k: PKw.Else, els: PSeqn)(val pos: (Position, Position)) extends PStmt with PIfContinuation { override def reformat(implicit ctx: ReformatterContext): Cont = { - show(k) <+> showBody(show(els), false) + show(k) <> showBody(els, false) } } case class PWhile(keyword: PKw.While, cond: PGrouped.Paren[PExp], invs: PDelimited[PSpecification[PKw.InvSpec], Option[PSym.Semi]], body: PSeqn)(val pos: (Position, Position)) extends PStmt { override def reformat(implicit ctx: ReformatterContext): Cont = { show(keyword) <> show(cond) <+> - showInvs(invs) <> showBody(show(body), !invs.isEmpty) + showInvs(invs) <> showBody(body, !invs.isEmpty) } } @@ -1931,7 +1931,7 @@ case class PDomain(annotations: Seq[PAnnotation], domain: PKw.Domain, idndef: PI showAnnotations(annotations) <@@> show(domain) <+> show(idndef) <> showOption(typVars) <> (if (interpretations.isEmpty) nil else nest(defaultIndent, linebreak <> showOption(interpretations))) <> - showBody(show(members), !interpretations.isEmpty) + showBody(members, !interpretations.isEmpty) } } @@ -2021,7 +2021,7 @@ case class PFunction(annotations: Seq[PAnnotation], keyword: PKw.Function, idnde println(s"body ${body}"); showAnnotations(annotations) <@@> show(keyword) <+> show(idndef) <> show(args) <> show(c) <+> show(resultType) <> - showPresPosts(pres, posts) <> showBody(showOption(body), !(pres.isEmpty && posts.isEmpty)) + showPresPosts(pres, posts) <> body.map(showBody(_, !(pres.isEmpty && posts.isEmpty))).getOrElse(nil) } } @@ -2031,7 +2031,7 @@ case class PPredicate(annotations: Seq[PAnnotation], keyword: PKw.Predicate, idn override def resultType = Predicate override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> show(keyword) <+> show(idndef) <> - show(args) <> showBody(showOption(body), false) + show(args) <> body.map(showBody(_, false)).getOrElse(nil) } case class PMethod(annotations: Seq[PAnnotation], keyword: PKw.Method, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PFormalArgDecl], returns: Option[PMethodReturns], pres: PDelimited[PSpecification[PKw.PreSpec], Option[PSym.Semi]], posts: PDelimited[PSpecification[PKw.PostSpec], Option[PSym.Semi]], body: Option[PSeqn]) @@ -2050,7 +2050,7 @@ case class PMethod(annotations: Seq[PAnnotation], keyword: PKw.Method, idndef: P // println(s"body ${body}"); // println(s"keyword pos: ${keyword.pos}"); showAnnotations(annotations) <@@> show(keyword) <+> show(idndef) <> show(args) <> showReturns(returns) <> - showPresPosts(pres, posts) <> showBody(showOption(body), !(returns.isEmpty && pres.isEmpty && posts.isEmpty)) + showPresPosts(pres, posts) <> body.map(showBody(_, !(returns.isEmpty && pres.isEmpty && posts.isEmpty))).getOrElse(nil) } } diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 5b50e9897..6c1a9a398 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -116,11 +116,11 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { nest(defaultIndent, (if (invs.isEmpty) nil else show(invs, SLinebreak()))) } - def showBody(body: Cont, newline: Boolean): Cont = { + def showBody(body: Reformattable, newline: Boolean)(implicit ctx: ReformatterContext): Cont = { if (newline) { - linebreak <> body + show(body, SLinebreak()) } else { - nil <+> body + show(body, SSpace()) } } From 10544dd2b24448bad6090568785e0f0c8d70578b Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Thu, 21 Nov 2024 17:15:07 +0100 Subject: [PATCH 21/47] more --- .../scala/viper/silver/parser/ParseAst.scala | 25 ++++++++++--------- .../silver/parser/ReformatPrettyPrinter.scala | 22 +++++++++++++--- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index b73da29c4..3804fc741 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -1076,7 +1076,7 @@ class PBinExp(val left: PExp, val op: PReserved[PBinaryOp], val right: PExp)(val op.rs match { // Those operators look a bit better if they stick on the previous line case Iff | Implies | EqEq => - group(show(left) <+> show(op) <> nest(defaultIndent, line <> show(right))) + group(show(left) <+> show(op) <> nest(defaultIndent, show(right, SLine()))) case _ => group(show(left) <@> show(op) <+> show(right)) } @@ -1106,8 +1106,8 @@ case class PCondExp(cond: PExp, q: PSymOp.Question, thn: PExp, c: PSymOp.Colon, ) override def reformatExp(implicit ctx: ReformatterContext): Cont = show(cond) <+> show(q) <> - nest(defaultIndent, group(line <> show(thn) <+> - show(c) <> group(line <> show(els)))) + nest(defaultIndent, group(show(thn, SLine()) <+> + show(c) <> group(show(els, SLine())))) } // Simple literals @@ -1174,7 +1174,7 @@ case class PUnfolding(unfolding: PKwOp.Unfolding, acc: PAccAssertion, in: PKwOp. override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Predicate, POpApp.pResS -> POpApp.pArg(1))) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(unfolding) <+> show(acc) <+> show(in) <> nest(defaultIndent, group(line <> show(exp))) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(unfolding) <+> show(acc) <+> show(in) <> nest(defaultIndent, group(show(exp, SLine()))) } case class PApplying(applying: PKwOp.Applying, wand: PExp, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { @@ -1182,7 +1182,7 @@ case class PApplying(applying: PKwOp.Applying, wand: PExp, in: PKwOp.In, exp: PE override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Wand, POpApp.pResS -> POpApp.pArg(1))) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(applying) <+> show(wand) <+> show(in) <> nest(defaultIndent, group(line <> show(exp))) + override def reformatExp(implicit ctx: ReformatterContext): Cont = show(applying) <+> show(wand) <+> show(in) <> nest(defaultIndent, group(show(exp, SLine()))) } case class PAsserting(asserting: PKwOp.Asserting, a: PExp, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { @@ -1191,8 +1191,8 @@ case class PAsserting(asserting: PKwOp.Asserting, a: PExp, in: PKwOp.In, exp: PE List(Map(POpApp.pArgS(0) -> Impure, POpApp.pResS -> POpApp.pArg(1))) override def reformatExp(implicit ctx: ReformatterContext): Cont = show(asserting) <+> - nest(defaultIndent, group(line <> show(a))) <+> - show(in) <> nest(defaultIndent, group(line <> show(exp))) + nest(defaultIndent, group(show(a, SLine()))) <+> + show(in) <> nest(defaultIndent, group(show(exp, SLine()))) } sealed trait PBinder extends PExp with PScope { @@ -1240,7 +1240,7 @@ case class PForPerm(keyword: PKw.Forperm, vars: PDelimited[PLogicalVarDecl, PSym override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <+> show(vars) <+> show(accessRes) <+> show(c) <> - nest(defaultIndent, group(line <> show(body))) + nest(defaultIndent, group(show(body, SLine()))) } /* Let-expressions `let x == e1 in e2` are represented by the nested structure @@ -1265,7 +1265,7 @@ case class PLet(l: PKwOp.Let, variable: PIdnDef, eq: PSymOp.EqEq, exp: PGrouped. } override def reformatExp(implicit ctx: ReformatterContext): Cont = show(l) <+> show(variable) <+> - show(eq) <+> show(exp) <+> show(in) <> group(line <> show(nestedScope)) + show(eq) <+> show(exp) <+> show(in) <> group(show(nestedScope, SLine())) } case class PLetNestedScope(body: PExp)(val pos: (Position, Position)) extends PTypedVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { @@ -1930,7 +1930,7 @@ case class PDomain(annotations: Seq[PAnnotation], domain: PKw.Domain, idndef: PI override def reformat(implicit ctx: ReformatterContext): Cont = { showAnnotations(annotations) <@@> show(domain) <+> show(idndef) <> showOption(typVars) <> - (if (interpretations.isEmpty) nil else nest(defaultIndent, linebreak <> showOption(interpretations))) <> + (if (interpretations.isEmpty) nil else nest(defaultIndent, showOption(interpretations, SLinebreak()))) <> showBody(members, !interpretations.isEmpty) } } @@ -1987,8 +1987,9 @@ case class PAxiom1(annotations: Seq[PAnnotation], axiom: PKw.Axiom, idndef: Opti showOption(idndef) <+@> show(exp) <> showOption(s) } case class PDomainMembers1(members: Seq[PDomainMember1])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(implicit ctx: ReformatterContext): Cont = if (members.isEmpty) nil else members.map(m => show(m)) - .reduce(_ <> linebreak <> _) + override def reformat(implicit ctx: ReformatterContext): Cont = if (members.isEmpty) nil else members.zipWithIndex + .map(m => if (m._2 == 0) show(m._1) else show(m._1, SLinebreak())) + .reduce(_ <> _) } diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 6c1a9a398..e5e199440 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -37,12 +37,28 @@ trait ReformattableExpression extends FastPrettyPrinterBase { class ReformatterContext(val program: String, val offsets: Seq[Int]) { var currentOffset: Int = 0 + var currentSeparator: Separator = SNil() def getByteOffset(p: HasLineColumn): Int = { val row = offsets(p.line - 1); row + p.column - 1 } +// def registerSeparator(sep: Separator) = { +// currentSeparator match { +// case SNil() => currentSeparator = sep +// case SSpace() => sep match { +// case SNil() => {} +// case _ => currentSeparator = sep +// } +// case SLine() | SLinebreak() => sep match { +// case SLine() | SLinebreak() | SDLinebreak() => currentSeparator = sep +// case _ => {} +// } +// case _ => {} +// } +// } + def getTrivia(pos: (ast.Position, ast.Position), updateOffset: Boolean): Seq[Trivia] = { (pos._1, pos._2) match { case (p: HasLineColumn, q: HasLineColumn) => { @@ -204,17 +220,17 @@ object ReformatPrettyPrinter extends FastPrettyPrinterBase { n match { case p: Reformattable => show(p, sep) case p: Option[Any] => showOption(p, sep) - case p: Seq[Any] => showSeq(p) + case p: Seq[Any] => showSeq(p, sep) case p: Right[Any, Any] => showAny(p.value, sep) case p: Left[Any, Any] => showAny(p.value, sep) } } - def showSeq(l: Seq[Any])(implicit ctx: ReformatterContext): Cont = { + def showSeq(l: Seq[Any], sep: Separator = SNil())(implicit ctx: ReformatterContext): Cont = { if (l.isEmpty) { nil } else { - l.map(showAny(_)).reduce(_ <> linebreak <> _) + l.zipWithIndex.map(e => if (e._2 == 0) showAny(e._1, sep) else showAny(e._1, SLinebreak())).reduce(_ <> _) } } } \ No newline at end of file From 9e513c55e90a56cc08b750e45f4f990210c235cd Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Thu, 21 Nov 2024 21:22:32 +0100 Subject: [PATCH 22/47] Create ReformatterPrettyPrinterBase --- .../silver/parser/ReformatPrettyPrinter.scala | 64 +++++++++++++++++-- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index e5e199440..176f2eff1 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -2,11 +2,63 @@ package viper.silver.parser import fastparse.Parsed import viper.silver.ast -import viper.silver.ast.pretty.FastPrettyPrinterBase -import viper.silver.ast.{HasLineColumn} +import viper.silver.ast.pretty.{Call, FastPrettyPrinterBase, PrettyPrintPrimitives} +import viper.silver.ast.HasLineColumn import viper.silver.parser.FastParserCompanion.programTrivia -sealed trait Separator extends FastPrettyPrinterBase { +sealed trait ReformatPrettyPrinterBase extends PrettyPrintPrimitives { + val defaultIndent = 4 + val defaultWidth = 75 + + implicit def char (c : Char) : Cont = + if (c == '\n') + line + else + text (c.toString) + + def space : Cont = + char (' ') + + def dlinebreak : Cont = + linebreak <> linebreak + + def line: Cont = line(" ") + + def linebreak : Cont = + line ("\n") + + implicit class ContOps(dl: Cont) { + def <>(dr: Cont) : Cont = + (iw: IW) => + (c: TreeCont) => { + Call(() => + for { + t <- dr(iw)(c) + t2 <- dl(iw)(t) + } yield t2) + } + + def <+> (dr : Cont) : Cont = + dl <> space <> dr + + def <@> (dr: Cont) : Cont = + if (dl == nil) dr else if (dr == nil) dl else dl <> line <> dr + + def <@@> (dr: Cont) : Cont = + if (dl == nil) dr else if (dr == nil) dl else dl <> linebreak <> dr + + def <@@@> (dr: Cont) : Cont = + if (dl == nil) dr else if (dr == nil) dl else dl <> dr + + def <@+> (dr: Cont) : Cont = + if (dl == nil) dr else if (dr == nil) dl else dl <> dr + + def <+@> (dr: Cont) : Cont = + if (dl == nil) dr else if (dr == nil) dl else dl <> space <> dr + } +} + +sealed trait Separator extends ReformatPrettyPrinterBase { def doc: Cont } @@ -27,11 +79,11 @@ case class SDLinebreak() extends Separator { } -trait Reformattable extends FastPrettyPrinterBase with Where { +trait Reformattable extends ReformatPrettyPrinterBase with Where { def reformat(implicit ctx: ReformatterContext): Cont } -trait ReformattableExpression extends FastPrettyPrinterBase { +trait ReformattableExpression extends ReformatPrettyPrinterBase { def reformatExp(implicit ctx: ReformatterContext): Cont } @@ -92,7 +144,7 @@ class ReformatterContext(val program: String, val offsets: Seq[Int]) { } } -object ReformatPrettyPrinter extends FastPrettyPrinterBase { +object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { override val defaultIndent = 4 def reformatProgram(p: PProgram): String = { From 34b806f76c012cf322408c56a67e4d112144bb33 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Fri, 22 Nov 2024 11:22:43 +0100 Subject: [PATCH 23/47] More progress --- .../scala/viper/silver/parser/ParseAst.scala | 19 +- .../silver/parser/ReformatPrettyPrinter.scala | 184 ++++++++++++++++-- 2 files changed, 184 insertions(+), 19 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 3804fc741..8e2863767 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -2103,24 +2103,37 @@ trait PExtender extends PNode { // Trivia (comments, whitespaces) trait Trivia extends FastPrettyPrinterBase { def display: Cont + def content: RNode } case class POther() extends Trivia { override def display: Cont = text("") + + override def content: RNode = RNil() } case class PSpace() extends Trivia { override def display: Cont = space + + override def content: RNode = RSpace() } case class PNewLine() extends Trivia { override def display: Cont = linebreak + + override def content: RNode = RLineBreak() } -case class PComment(content: String, block: Boolean) extends Trivia { +case class PComment(inner: String, block: Boolean) extends Trivia { def display: Cont = if (block) { - text("/*") <> content <> text("*/") + text("/*") <> inner <> text("*/") + } else { + text("//") <> text(inner) + } + + override def content: RNode = if (block) { + RText("/*" + inner + "*/") } else { - text("//") <> text(content) + RText("//" + inner) } } \ No newline at end of file diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 176f2eff1..1d423dbed 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -5,6 +5,45 @@ import viper.silver.ast import viper.silver.ast.pretty.{Call, FastPrettyPrinterBase, PrettyPrintPrimitives} import viper.silver.ast.HasLineColumn import viper.silver.parser.FastParserCompanion.programTrivia +import viper.silver.parser.RLineBreak.rlb +import viper.silver.parser.RNest.rne +import viper.silver.parser.RNil.rn +import viper.silver.parser.RSpace.rs + +trait RNode {} + +case class RNil() extends RNode +object RNil { + def rn(): List[RNode] = List(RNil()) +} +case class RText(text: String) extends RNode +object RText { + def rt(text: String): List[RNode] = List(RText(text)) +} +case class RSpace() extends RNode +object RSpace { + def rs(): List[RNode] = List(RSpace()) +} +case class RNest(l: List[RNode]) extends RNode +object RNest { + def rne(l: List[RNode]): List[RNode] = List(RNest(l)) +} +case class RGroup(l: List[RNode]) extends RNode +object RGroup { + def rg(l: List[RNode]): List[RNode] = List(RGroup(l)) +} +case class RLine() extends RNode +object RLine { + def rl(): List[RNode] = List(RLine()) +} +case class RLineBreak() extends RNode +object RLineBreak { + def rlb(): List[RNode] = List(RLineBreak()) +} +case class RDLineBreak() extends RNode +object RDLineBreak { + def rdlb(): List[RNode] = List(RDLineBreak()) +} sealed trait ReformatPrettyPrinterBase extends PrettyPrintPrimitives { val defaultIndent = 4 @@ -81,6 +120,7 @@ case class SDLinebreak() extends Separator { trait Reformattable extends ReformatPrettyPrinterBase with Where { def reformat(implicit ctx: ReformatterContext): Cont + def reformat2(implicit ctx: ReformatterContext2): List[RNode] = throw new IllegalAccessException(s"reformat2 not implemented ${getClass}") } trait ReformattableExpression extends ReformatPrettyPrinterBase { @@ -89,28 +129,12 @@ trait ReformattableExpression extends ReformatPrettyPrinterBase { class ReformatterContext(val program: String, val offsets: Seq[Int]) { var currentOffset: Int = 0 - var currentSeparator: Separator = SNil() def getByteOffset(p: HasLineColumn): Int = { val row = offsets(p.line - 1); row + p.column - 1 } -// def registerSeparator(sep: Separator) = { -// currentSeparator match { -// case SNil() => currentSeparator = sep -// case SSpace() => sep match { -// case SNil() => {} -// case _ => currentSeparator = sep -// } -// case SLine() | SLinebreak() => sep match { -// case SLine() | SLinebreak() | SDLinebreak() => currentSeparator = sep -// case _ => {} -// } -// case _ => {} -// } -// } - def getTrivia(pos: (ast.Position, ast.Position), updateOffset: Boolean): Seq[Trivia] = { (pos._1, pos._2) match { case (p: HasLineColumn, q: HasLineColumn) => { @@ -285,4 +309,132 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { l.zipWithIndex.map(e => if (e._2 == 0) showAny(e._1, sep) else showAny(e._1, SLinebreak())).reduce(_ <> _) } } +} + +class ReformatterContext2(val program: String, val offsets: Seq[Int]) { + var currentOffset: Int = 0 + + def getByteOffset(p: HasLineColumn): Int = { + val row = offsets(p.line - 1); + row + p.column - 1 + } + + def getTrivia(pos: (ast.Position, ast.Position), updateOffset: Boolean): List[RNode] = { + (pos._1, pos._2) match { + case (p: HasLineColumn, q: HasLineColumn) => { + val p_offset = getByteOffset(p); + val q_offset = getByteOffset(q); + getTriviaByByteOffset(p_offset, if (updateOffset) Some(q_offset) else None) + } + case _ => List() + } + } + + def getTriviaByByteOffset(offset: Int, updateOffset: Option[Int]): List[RNode] = { + if (currentOffset <= offset) { + val str = program.substring(currentOffset, offset); + currentOffset = currentOffset.max(offset); + + updateOffset match { + case Some(o) => currentOffset = o + case _ => + } + + fastparse.parse(str, programTrivia(_)) match { + case Parsed.Success(value, _) => { + value.map(_.content).toList + } + case _: Parsed.Failure => List() + } + } else { + List() + }; + } +} + +object ReformatPrettyPrinter2 extends ReformatPrettyPrinterBase { + def reformatProgram(p: PProgram): String = { + implicit val ctx = new ReformatterContext2(p.rawProgram, p.offsets) + + def showList(p: List[RNode]): Cont = if (p.isEmpty) nil else p.map(n => n match { + case RNil() => nil + case RText(t: String) => text(t) + case RSpace() => space + case RGroup(l: List[RNode]) => group(showList(l)) + case RLine() => line + case RLineBreak() => linebreak + case RDLineBreak() => linebreak <> linebreak + }).reduce(_ <> _) + + super.pretty(defaultWidth, showList(show(p))) + } + + def showOption[T <: Any](n: Option[T])(implicit ctx: ReformatterContext2): List[RNode] = { + n match { + case Some(r) => showAny(r) + case None => rn + } + } + + def showAnnotations(annotations: Seq[PAnnotation])(implicit ctx: ReformatterContext2): List[RNode] = { + if (annotations.isEmpty) { + List(RNil()) + } else { + annotations.map(show(_)).reduce((acc, n) => acc ::: n) + } + } + + def showReturns(returns: Option[PMethodReturns])(implicit ctx: ReformatterContext2): List[RNode] = { + returns.map(a => rs ::: show(a)).getOrElse(rn) + } + + def showPresPosts(pres: PDelimited[_, _], posts: PDelimited[_, _])(implicit ctx: ReformatterContext2): List[RNode] = { + rne((if (pres.isEmpty) rn + else rlb ::: show(pres)) ::: + (if (posts.isEmpty) rn + else rlb ::: show(posts) + ) + ) + } + + def showInvs(invs: PDelimited[_, _])(implicit ctx: ReformatterContext2): List[RNode] = { + rne(if (invs.isEmpty) rn else rlb ::: show(invs)) + } + + def showBody(body: Reformattable, newline: Boolean)(implicit ctx: ReformatterContext2): List[RNode] = { + if (newline) { + rlb ::: show(body) + } else { + rs ::: show(body) + } + } + + def show(r: Reformattable)(implicit ctx: ReformatterContext2): List[RNode] = { + val updatePos = r match { + case _: PLeaf => true + case _ => false + } + + val trivia = ctx.getTrivia(r.pos, updatePos); + + trivia ::: r.reformat2(ctx) + } + + def showAny(n: Any)(implicit ctx: ReformatterContext2): List[RNode] = { + n match { + case p: Reformattable => show(p) + case p: Option[Any] => showOption(p) + case p: Seq[Any] => showSeq(p) + case p: Right[Any, Any] => showAny(p.value) + case p: Left[Any, Any] => showAny(p.value) + } + } + + def showSeq(l: Seq[Any])(implicit ctx: ReformatterContext2): List[RNode] = { + if (l.isEmpty) { + rn + } else { + l.zipWithIndex.map(e => if (e._2 == 0) showAny(e._1) else rlb ::: showAny(e._1)).reduce(_ ::: _) + } + } } \ No newline at end of file From 4289eadbaa279fe0b1ccc9aaa938c478fb91df48 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Fri, 22 Nov 2024 12:29:03 +0100 Subject: [PATCH 24/47] more progress towards new reformatter --- .../scala/viper/silver/parser/ParseAst.scala | 29 ++-- .../viper/silver/parser/ParseAstKeyword.scala | 42 ++++- .../silver/parser/ReformatPrettyPrinter.scala | 143 ++++++++++++------ 3 files changed, 155 insertions(+), 59 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 8e2863767..c78880d06 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -17,6 +17,10 @@ import viper.silver.ast.utility.Visitor import viper.silver.ast.utility.rewriter.{HasExtraValList, HasExtraVars, Rewritable, StrategyBuilder} import viper.silver.ast.{Exp, Member, NoPosition, SourcePosition, Stmt, Type} import viper.silver.parser.PSymOp.{EqEq, Iff, Implies} +import viper.silver.parser.RLineBreak.rlb +import viper.silver.parser.RNil.rn +import viper.silver.parser.RText.rt +import viper.silver.parser.ReformatPrettyPrinter2.{show2, showAnnotations2, showBody2, showPresPosts2, showReturns2} import viper.silver.parser.TypeHelper._ import viper.silver.verifier.ParseReport @@ -240,6 +244,8 @@ trait PIdentifier extends PLeaf { case class PIdnDef(name: String)(val pos: (Position, Position)) extends PNode with PIdentifier { override def reformat(implicit ctx: ReformatterContext): Cont = text(name) + + override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = rt(name) } trait PIdnUse extends PNode with PIdentifier { @@ -1631,6 +1637,8 @@ case class PSeqn(ss: PDelimited.Block[PStmt])(val pos: (Position, Position)) ext override def pretty = ss.prettyLines override def reformat(implicit ctx: ReformatterContext): Cont = show(ss) + + override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = show2(ss) } /** @@ -1889,6 +1897,13 @@ case class PProgram(imported: Seq[PProgram], members: Seq[PMember])(val pos: (Po members.zipWithIndex.map(e => show(e._1, if (e._2 == 0) SNil() else SLinebreak())).reduce((acc, n) => acc <> n) } + override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = { + if (members.isEmpty) + rn + else + members.zipWithIndex.map(e => (if (e._2 == 0) rn else rlb) <> show2(e._1)).reduce((acc, n) => acc <> n) + } + // Pretty print members in a specific order def prettyOrdered: String = { val all = Seq(imports, macros, domains, fields, functions, predicates, methods, extensions).filter(_.length > 0) @@ -2041,18 +2056,14 @@ case class PMethod(annotations: Seq[PAnnotation], keyword: PKw.Method, idndef: P override def returnNodes = returns.toSeq override def reformat(implicit ctx: ReformatterContext): Cont = { - // TODO: Test annotations -// println(s"PMethod"); -// println(s"---------------------------"); -// println(s"args ${args}"); -// println(s"returns ${returns}"); -// println(s"pres ${pres}"); -// println(s"posts ${posts}"); -// println(s"body ${body}"); -// println(s"keyword pos: ${keyword.pos}"); showAnnotations(annotations) <@@> show(keyword) <+> show(idndef) <> show(args) <> showReturns(returns) <> showPresPosts(pres, posts) <> body.map(showBody(_, !(returns.isEmpty && pres.isEmpty && posts.isEmpty))).getOrElse(nil) } + + override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = { + showAnnotations2(annotations) <-> show2(keyword) <+> show2(idndef) <> show2(args) <> showReturns2(returns) <> + showPresPosts2(pres, posts) <> body.map(showBody2(_, !(returns.isEmpty && pres.isEmpty && posts.isEmpty))).getOrElse(rn) + } } case class PMethodReturns(k: PKw.Returns, formalReturns: PGrouped.Paren[PDelimited[PFormalReturnDecl, PSym.Comma]])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { diff --git a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala index 3c1f2bd70..8bd28aa4e 100644 --- a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala +++ b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala @@ -8,7 +8,14 @@ package viper.silver.parser import viper.silver.ast.{NoPosition, Position} import viper.silver.parser.PSym.Brace +import viper.silver.parser.RLine.rl +import viper.silver.parser.RLineBreak.rlb +import viper.silver.parser.RNest.rne +import viper.silver.parser.RNil.rn +import viper.silver.parser.RSpace.rs +import viper.silver.parser.RText.rt import viper.silver.parser.ReformatPrettyPrinter.{show, showAny} +import viper.silver.parser.ReformatPrettyPrinter2.{show2, showAny2} import viper.silver.parser.TypeHelper._ trait PReservedString { @@ -25,6 +32,8 @@ case class PReserved[+T <: PReservedString](rs: T)(val pos: (Position, Position) def token = rs.token override def reformat(implicit ctx: ReformatterContext): Cont = text(token) + + override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = rt(token) } object PReserved { def implied[T <: PReservedString](rs: T): PReserved[T] = PReserved(rs)(NoPosition, NoPosition) @@ -52,6 +61,21 @@ case class PGrouped[G <: PSym.Group, +T](l: PReserved[G#L], inner: T, r: PReserv show(l) <> nest(defaultIndent, showAny(inner)) <> show(r) } } + + override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = { + if (l.rs.isInstanceOf[Brace]) { + val left = show2(l); + val inner_ = showAny2(inner); + val right = show2(r); + if (inner_.forall(_.isNil)) { + left <> right + } else { + left <> rne(rl <> inner_) <> rl <> right + } + } else { + show2(l) <> rne(showAny2(inner)) <> show2(r) + } + } } object PGrouped { /** Grouped and delimited. */ @@ -106,12 +130,6 @@ class PDelimited[+T, +D]( override def toString(): String = s"PDelimited($first,$inner,$end)" override def reformat(implicit ctx: ReformatterContext): Cont = { -// println(s"PDelimited"); -// println(s"---------------------------"); -// println(s"first: ${first}"); -// println(s"inner: ${inner}"); -// println(s"end: ${end}"); - val separator = delimiters.headOption match { case Some(p: PSym.Comma) => SSpace() case None => SNil() @@ -122,6 +140,18 @@ class PDelimited[+T, +D]( inner.foldLeft(nil)((acc, b) => acc <@@@> showAny(b._1) <@@@> showAny(b._2, separator)) <@@@> showAny(end) } + + override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = { + val separator = delimiters.headOption match { + case Some(p: PSym.Comma) => rs + case None => rn + case _ => rlb + }; + + showAny2(first) <> + inner.foldLeft(rn)((acc, b) => acc <> showAny2(b._1) <> separator <> showAny2(b._2)) <> + showAny2(end) + } } object PDelimited { diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 1d423dbed..94c456dc1 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -5,44 +5,76 @@ import viper.silver.ast import viper.silver.ast.pretty.{Call, FastPrettyPrinterBase, PrettyPrintPrimitives} import viper.silver.ast.HasLineColumn import viper.silver.parser.FastParserCompanion.programTrivia +import viper.silver.parser.RLine.rl import viper.silver.parser.RLineBreak.rlb import viper.silver.parser.RNest.rne import viper.silver.parser.RNil.rn import viper.silver.parser.RSpace.rs -trait RNode {} +trait RNode { + def isNil: Boolean +} + +trait RWhitespace extends RNode -case class RNil() extends RNode +case class RNil() extends RNode { + override def isNil: Boolean = true +} object RNil { def rn(): List[RNode] = List(RNil()) } -case class RText(text: String) extends RNode + +case class RText(text: String) extends RNode { + override def isNil: Boolean = text.isEmpty +} object RText { def rt(text: String): List[RNode] = List(RText(text)) } -case class RSpace() extends RNode -object RSpace { - def rs(): List[RNode] = List(RSpace()) + +case class RNest(l: List[RNode]) extends RNode { + override def isNil: Boolean = l.forall(_.isNil) } -case class RNest(l: List[RNode]) extends RNode object RNest { def rne(l: List[RNode]): List[RNode] = List(RNest(l)) } -case class RGroup(l: List[RNode]) extends RNode + +case class RGroup(l: List[RNode]) extends RNode { + override def isNil: Boolean = l.forall(_.isNil) +} object RGroup { def rg(l: List[RNode]): List[RNode] = List(RGroup(l)) } -case class RLine() extends RNode + +case class RHard(w: RWhitespace) extends RNode { + override def isNil: Boolean = false +} + +case class RSpace() extends RWhitespace { + override def isNil: Boolean = false +} +object RSpace { + def rs(): List[RNode] = List(RHard(RSpace())) +} + +case class RLine() extends RWhitespace { + override def isNil: Boolean = false +} object RLine { - def rl(): List[RNode] = List(RLine()) + def rl(): List[RNode] = List(RHard(RLine())) +} + +case class RLineBreak() extends RWhitespace { + override def isNil: Boolean = false } -case class RLineBreak() extends RNode object RLineBreak { - def rlb(): List[RNode] = List(RLineBreak()) + def rlb(): List[RNode] =List(RHard(RLineBreak())) +} + +case class RDLineBreak() extends RWhitespace { + override def isNil: Boolean = false } -case class RDLineBreak() extends RNode object RDLineBreak { - def rdlb(): List[RNode] = List(RDLineBreak()) + def rdlb(): List[RNode] = List(RHard(RDLineBreak())) } sealed trait ReformatPrettyPrinterBase extends PrettyPrintPrimitives { @@ -66,6 +98,20 @@ sealed trait ReformatPrettyPrinterBase extends PrettyPrintPrimitives { def linebreak : Cont = line ("\n") + implicit class ContOps2(dl: List[RNode]) { + def <>(dr: List[RNode]): List[RNode] = + dl ::: dr + + def <+>(dr: List[RNode]): List[RNode] = + if (dr.forall(_.isNil)) dl else if (dl.forall(_.isNil)) dr else dl ::: rs ::: dr + + def <@>(dr: List[RNode]): List[RNode] = + if (dr.forall(_.isNil)) dl else if (dl.forall(_.isNil)) dr else dl ::: rl ::: dr + + def <->(dr: List[RNode]): List[RNode] = + if (dr.forall(_.isNil)) dl else if (dl.forall(_.isNil)) dr else dl ::: rlb ::: dr + } + implicit class ContOps(dl: Cont) { def <>(dr: Cont) : Cont = (iw: IW) => @@ -125,6 +171,7 @@ trait Reformattable extends ReformatPrettyPrinterBase with Where { trait ReformattableExpression extends ReformatPrettyPrinterBase { def reformatExp(implicit ctx: ReformatterContext): Cont + def reformatExp2(implicit ctx: ReformatterContext2): List[RNode] = throw new IllegalAccessException(s"reformatExt2 not implemented ${getClass}") } class ReformatterContext(val program: String, val offsets: Seq[Int]) { @@ -172,6 +219,7 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { override val defaultIndent = 4 def reformatProgram(p: PProgram): String = { + println(s"${p}"); implicit val ctx = new ReformatterContext(p.rawProgram, p.offsets) super.pretty(defaultWidth, show(p)) } @@ -222,9 +270,9 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { case _ => false } - println(s"separator: ${sep}"); - println(s"pos: ${r.pos}"); - println(s"node: ${r.getClass}"); +// println(s"separator: ${sep}"); +// println(s"pos: ${r.pos}"); +// println(s"node: ${r.getClass}"); val trivia = ctx.getTrivia(r.pos, updatePos); @@ -242,7 +290,7 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { else SNil() } - println(trivia); +// println(trivia); for (t <- trivia) { t match { @@ -353,63 +401,70 @@ class ReformatterContext2(val program: String, val offsets: Seq[Int]) { } object ReformatPrettyPrinter2 extends ReformatPrettyPrinterBase { - def reformatProgram(p: PProgram): String = { + def reformatProgram2(p: PProgram): String = { implicit val ctx = new ReformatterContext2(p.rawProgram, p.offsets) def showList(p: List[RNode]): Cont = if (p.isEmpty) nil else p.map(n => n match { case RNil() => nil - case RText(t: String) => text(t) + case RText(t: String) => { + println(s"Found text: ${}, ${}", t, t.length) + text(t) + } case RSpace() => space + case RHard(w) => showList(List(w)) case RGroup(l: List[RNode]) => group(showList(l)) + case RNest(l: List[RNode]) => nest(defaultIndent, showList(l)) case RLine() => line case RLineBreak() => linebreak case RDLineBreak() => linebreak <> linebreak }).reduce(_ <> _) - super.pretty(defaultWidth, showList(show(p))) + val list = show2(p).filter(!_.isNil) + println(s"List: ${list}") + super.pretty(defaultWidth, showList(list)) } - def showOption[T <: Any](n: Option[T])(implicit ctx: ReformatterContext2): List[RNode] = { + def showOption2[T <: Any](n: Option[T])(implicit ctx: ReformatterContext2): List[RNode] = { n match { - case Some(r) => showAny(r) + case Some(r) => showAny2(r) case None => rn } } - def showAnnotations(annotations: Seq[PAnnotation])(implicit ctx: ReformatterContext2): List[RNode] = { + def showAnnotations2(annotations: Seq[PAnnotation])(implicit ctx: ReformatterContext2): List[RNode] = { if (annotations.isEmpty) { List(RNil()) } else { - annotations.map(show(_)).reduce((acc, n) => acc ::: n) + annotations.map(show2(_)).reduce((acc, n) => acc ::: n) } } - def showReturns(returns: Option[PMethodReturns])(implicit ctx: ReformatterContext2): List[RNode] = { - returns.map(a => rs ::: show(a)).getOrElse(rn) + def showReturns2(returns: Option[PMethodReturns])(implicit ctx: ReformatterContext2): List[RNode] = { + returns.map(a => rs ::: show2(a)).getOrElse(rn) } - def showPresPosts(pres: PDelimited[_, _], posts: PDelimited[_, _])(implicit ctx: ReformatterContext2): List[RNode] = { + def showPresPosts2(pres: PDelimited[_, _], posts: PDelimited[_, _])(implicit ctx: ReformatterContext2): List[RNode] = { rne((if (pres.isEmpty) rn - else rlb ::: show(pres)) ::: + else rlb ::: show2(pres)) ::: (if (posts.isEmpty) rn - else rlb ::: show(posts) + else rlb ::: show2(posts) ) ) } - def showInvs(invs: PDelimited[_, _])(implicit ctx: ReformatterContext2): List[RNode] = { - rne(if (invs.isEmpty) rn else rlb ::: show(invs)) + def showInvs2(invs: PDelimited[_, _])(implicit ctx: ReformatterContext2): List[RNode] = { + rne(if (invs.isEmpty) rn else rlb ::: show2(invs)) } - def showBody(body: Reformattable, newline: Boolean)(implicit ctx: ReformatterContext2): List[RNode] = { + def showBody2(body: Reformattable, newline: Boolean)(implicit ctx: ReformatterContext2): List[RNode] = { if (newline) { - rlb ::: show(body) + rlb ::: show2(body) } else { - rs ::: show(body) + rs ::: show2(body) } } - def show(r: Reformattable)(implicit ctx: ReformatterContext2): List[RNode] = { + def show2(r: Reformattable)(implicit ctx: ReformatterContext2): List[RNode] = { val updatePos = r match { case _: PLeaf => true case _ => false @@ -420,21 +475,21 @@ object ReformatPrettyPrinter2 extends ReformatPrettyPrinterBase { trivia ::: r.reformat2(ctx) } - def showAny(n: Any)(implicit ctx: ReformatterContext2): List[RNode] = { + def showAny2(n: Any)(implicit ctx: ReformatterContext2): List[RNode] = { n match { - case p: Reformattable => show(p) - case p: Option[Any] => showOption(p) - case p: Seq[Any] => showSeq(p) - case p: Right[Any, Any] => showAny(p.value) - case p: Left[Any, Any] => showAny(p.value) + case p: Reformattable => show2(p) + case p: Option[Any] => showOption2(p) + case p: Seq[Any] => showSeq2(p) + case p: Right[Any, Any] => showAny2(p.value) + case p: Left[Any, Any] => showAny2(p.value) } } - def showSeq(l: Seq[Any])(implicit ctx: ReformatterContext2): List[RNode] = { + def showSeq2(l: Seq[Any])(implicit ctx: ReformatterContext2): List[RNode] = { if (l.isEmpty) { rn } else { - l.zipWithIndex.map(e => if (e._2 == 0) showAny(e._1) else rlb ::: showAny(e._1)).reduce(_ ::: _) + l.zipWithIndex.map(e => if (e._2 == 0) showAny2(e._1) else rlb ::: showAny2(e._1)).reduce(_ ::: _) } } } \ No newline at end of file From f6a85f1b7c87d7282bf49df1e9bf878195c927f3 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Fri, 22 Nov 2024 15:06:26 +0100 Subject: [PATCH 25/47] First seeminly working prototype --- .../scala/viper/silver/parser/ParseAst.scala | 13 +- .../silver/parser/ReformatPrettyPrinter.scala | 226 ++++++++++++++---- 2 files changed, 176 insertions(+), 63 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index c78880d06..0fad37ee9 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -2114,25 +2114,18 @@ trait PExtender extends PNode { // Trivia (comments, whitespaces) trait Trivia extends FastPrettyPrinterBase { def display: Cont - def content: RNode } case class POther() extends Trivia { override def display: Cont = text("") - - override def content: RNode = RNil() } case class PSpace() extends Trivia { override def display: Cont = space - - override def content: RNode = RSpace() } case class PNewLine() extends Trivia { override def display: Cont = linebreak - - override def content: RNode = RLineBreak() } case class PComment(inner: String, block: Boolean) extends Trivia { @@ -2142,9 +2135,9 @@ case class PComment(inner: String, block: Boolean) extends Trivia { text("//") <> text(inner) } - override def content: RNode = if (block) { - RText("/*" + inner + "*/") + def str: String = if (block) { + "/*" + inner + "*/" } else { - RText("//" + inner) + "//" + inner } } \ No newline at end of file diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 94c456dc1..1f06abf89 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -2,8 +2,8 @@ package viper.silver.parser import fastparse.Parsed import viper.silver.ast -import viper.silver.ast.pretty.{Call, FastPrettyPrinterBase, PrettyPrintPrimitives} import viper.silver.ast.HasLineColumn +import viper.silver.ast.pretty.{Call, PrettyPrintPrimitives} import viper.silver.parser.FastParserCompanion.programTrivia import viper.silver.parser.RLine.rl import viper.silver.parser.RLineBreak.rlb @@ -11,15 +11,20 @@ import viper.silver.parser.RNest.rne import viper.silver.parser.RNil.rn import viper.silver.parser.RSpace.rs +import scala.collection.mutable.ArrayBuffer + trait RNode { def isNil: Boolean } trait RWhitespace extends RNode +trait RCommentFragment + case class RNil() extends RNode { override def isNil: Boolean = true } + object RNil { def rn(): List[RNode] = List(RNil()) } @@ -27,13 +32,36 @@ object RNil { case class RText(text: String) extends RNode { override def isNil: Boolean = text.isEmpty } + object RText { def rt(text: String): List[RNode] = List(RText(text)) } +case class RTrivia(l: List[RCommentFragment]) extends RNode { + override def isNil: Boolean = l.isEmpty + + def hasComment(): Boolean = l.exists(_ match { + case RComment(_) => true + case _ => false + }) + + def lw(): Option[RWhitespace] = l.headOption.flatMap(_ match { + case w: RWhitespace => Some(w) + case _ => None + }) + + def trimmedTw(): RTrivia = l.lastOption match { + case Some(_: RWhitespace) => RTrivia(l.init) + case _ => this + } +} + +case class RComment(comment: PComment) extends RCommentFragment + case class RNest(l: List[RNode]) extends RNode { override def isNil: Boolean = l.forall(_.isNil) } + object RNest { def rne(l: List[RNode]): List[RNode] = List(RNest(l)) } @@ -41,62 +69,65 @@ object RNest { case class RGroup(l: List[RNode]) extends RNode { override def isNil: Boolean = l.forall(_.isNil) } + object RGroup { def rg(l: List[RNode]): List[RNode] = List(RGroup(l)) } -case class RHard(w: RWhitespace) extends RNode { +case class RSpace() extends RWhitespace with RCommentFragment { override def isNil: Boolean = false } -case class RSpace() extends RWhitespace { - override def isNil: Boolean = false -} object RSpace { - def rs(): List[RNode] = List(RHard(RSpace())) + def rs(): List[RNode] = List(RSpace()) } case class RLine() extends RWhitespace { override def isNil: Boolean = false } + object RLine { - def rl(): List[RNode] = List(RHard(RLine())) + def rl(): List[RNode] = List(RLine()) } -case class RLineBreak() extends RWhitespace { +case class RLineBreak() extends RWhitespace with RCommentFragment { override def isNil: Boolean = false } + object RLineBreak { - def rlb(): List[RNode] =List(RHard(RLineBreak())) + def rlb(): List[RNode] = List(RLineBreak()) } -case class RDLineBreak() extends RWhitespace { +case class RDLineBreak() extends RWhitespace with RCommentFragment { override def isNil: Boolean = false } -object RDLineBreak { - def rdlb(): List[RNode] = List(RHard(RDLineBreak())) + +object RDLineBreak extends RWhitespace { + def rdlb(): List[RNode] = List(RDLineBreak()) + + override def isNil: Boolean = false } sealed trait ReformatPrettyPrinterBase extends PrettyPrintPrimitives { val defaultIndent = 4 val defaultWidth = 75 - implicit def char (c : Char) : Cont = + implicit def char(c: Char): Cont = if (c == '\n') line else - text (c.toString) + text(c.toString) - def space : Cont = - char (' ') + def space: Cont = + char(' ') - def dlinebreak : Cont = + def dlinebreak: Cont = linebreak <> linebreak def line: Cont = line(" ") - def linebreak : Cont = - line ("\n") + def linebreak: Cont = + line("\n") implicit class ContOps2(dl: List[RNode]) { def <>(dr: List[RNode]): List[RNode] = @@ -113,7 +144,7 @@ sealed trait ReformatPrettyPrinterBase extends PrettyPrintPrimitives { } implicit class ContOps(dl: Cont) { - def <>(dr: Cont) : Cont = + def <>(dr: Cont): Cont = (iw: IW) => (c: TreeCont) => { Call(() => @@ -123,22 +154,22 @@ sealed trait ReformatPrettyPrinterBase extends PrettyPrintPrimitives { } yield t2) } - def <+> (dr : Cont) : Cont = + def <+>(dr: Cont): Cont = dl <> space <> dr - def <@> (dr: Cont) : Cont = + def <@>(dr: Cont): Cont = if (dl == nil) dr else if (dr == nil) dl else dl <> line <> dr - def <@@> (dr: Cont) : Cont = + def <@@>(dr: Cont): Cont = if (dl == nil) dr else if (dr == nil) dl else dl <> linebreak <> dr - def <@@@> (dr: Cont) : Cont = + def <@@@>(dr: Cont): Cont = if (dl == nil) dr else if (dr == nil) dl else dl <> dr - def <@+> (dr: Cont) : Cont = + def <@+>(dr: Cont): Cont = if (dl == nil) dr else if (dr == nil) dl else dl <> dr - def <+@> (dr: Cont) : Cont = + def <+@>(dr: Cont): Cont = if (dl == nil) dr else if (dr == nil) dl else dl <> space <> dr } } @@ -150,15 +181,19 @@ sealed trait Separator extends ReformatPrettyPrinterBase { case class SNil() extends Separator { override def doc: Cont = nil } + case class SSpace() extends Separator { override def doc: Cont = space } + case class SLine() extends Separator { override def doc: Cont = line } + case class SLinebreak() extends Separator { override def doc: Cont = linebreak } + case class SDLinebreak() extends Separator { override def doc: Cont = dlinebreak } @@ -166,11 +201,13 @@ case class SDLinebreak() extends Separator { trait Reformattable extends ReformatPrettyPrinterBase with Where { def reformat(implicit ctx: ReformatterContext): Cont + def reformat2(implicit ctx: ReformatterContext2): List[RNode] = throw new IllegalAccessException(s"reformat2 not implemented ${getClass}") } trait ReformattableExpression extends ReformatPrettyPrinterBase { def reformatExp(implicit ctx: ReformatterContext): Cont + def reformatExp2(implicit ctx: ReformatterContext2): List[RNode] = throw new IllegalAccessException(s"reformatExt2 not implemented ${getClass}") } @@ -270,9 +307,9 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { case _ => false } -// println(s"separator: ${sep}"); -// println(s"pos: ${r.pos}"); -// println(s"node: ${r.getClass}"); + // println(s"separator: ${sep}"); + // println(s"pos: ${r.pos}"); + // println(s"node: ${r.getClass}"); val trivia = ctx.getTrivia(r.pos, updatePos); @@ -290,7 +327,7 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { else SNil() } -// println(trivia); + // println(trivia); for (t <- trivia) { t match { @@ -300,7 +337,7 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { leadingSpaces = spaces; hasComment = true; nil - } else { + } else { getSep(newlines, spaces).doc } reformatted = reformatted <> lw <> p.display @@ -367,18 +404,18 @@ class ReformatterContext2(val program: String, val offsets: Seq[Int]) { row + p.column - 1 } - def getTrivia(pos: (ast.Position, ast.Position), updateOffset: Boolean): List[RNode] = { + def getTrivia(pos: (ast.Position, ast.Position), updateOffset: Boolean): RTrivia = { (pos._1, pos._2) match { case (p: HasLineColumn, q: HasLineColumn) => { val p_offset = getByteOffset(p); val q_offset = getByteOffset(q); getTriviaByByteOffset(p_offset, if (updateOffset) Some(q_offset) else None) } - case _ => List() + case _ => RTrivia(List()) } } - def getTriviaByByteOffset(offset: Int, updateOffset: Option[Int]): List[RNode] = { + def getTriviaByByteOffset(offset: Int, updateOffset: Option[Int]): RTrivia = { if (currentOffset <= offset) { val str = program.substring(currentOffset, offset); currentOffset = currentOffset.max(offset); @@ -390,38 +427,121 @@ class ReformatterContext2(val program: String, val offsets: Seq[Int]) { fastparse.parse(str, programTrivia(_)) match { case Parsed.Success(value, _) => { - value.map(_.content).toList + val trivia = ArrayBuffer[RCommentFragment]() + var newlines = 0 + var spaces = 0 + + for (t <- value) { + t match { + case p: PComment => { + if (newlines > 1) { + trivia += RDLineBreak() + } else if (newlines > 0) { + trivia += RLineBreak() + } else if (spaces > 0) { + trivia += RSpace() + } + + trivia += RComment(p) + + newlines = 0 + spaces = 0 + } + case w: PNewLine => newlines += 1 + case w: PSpace => spaces += 1 + case _ => {} + } + } + + RTrivia(trivia.toList) } - case _: Parsed.Failure => List() + case _: Parsed.Failure => RTrivia(List()) } } else { - List() + RTrivia(List()) }; } } +class PrintContext() { + var whitespace: Option[RWhitespace] = None + + def register(w: RWhitespace): Unit = { + whitespace match { + case None => whitespace = Some(w) + case Some(p: RLineBreak) => w match { + case p: RLineBreak => whitespace = Some(RDLineBreak) + case p: RDLineBreak => whitespace = Some(RDLineBreak) + } + case Some(p) => whitespace = Some(p) + } + } +} + object ReformatPrettyPrinter2 extends ReformatPrettyPrinterBase { def reformatProgram2(p: PProgram): String = { implicit val ctx = new ReformatterContext2(p.rawProgram, p.offsets) - def showList(p: List[RNode]): Cont = if (p.isEmpty) nil else p.map(n => n match { - case RNil() => nil - case RText(t: String) => { - println(s"Found text: ${}, ${}", t, t.length) - text(t) + def showWhitespace(w: Option[RWhitespace]): Cont = { + w match { + case None => nil + case Some(RSpace()) => space + case Some(RLine()) => line + case Some(RLineBreak()) => linebreak + case Some(RDLineBreak()) => linebreak <> linebreak + } + } + + def showTrivia(p: RTrivia, pc: PrintContext): Cont = { + if (p.l.isEmpty) { + nil + } else { + p.l.map(t => t match { + case w: RWhitespace => showWhitespace(Some(w)) + case p: RComment => text(p.comment.str) + }).reduce((acc, n) => acc <> n) } - case RSpace() => space - case RHard(w) => showList(List(w)) - case RGroup(l: List[RNode]) => group(showList(l)) - case RNest(l: List[RNode]) => nest(defaultIndent, showList(l)) - case RLine() => line - case RLineBreak() => linebreak - case RDLineBreak() => linebreak <> linebreak - }).reduce(_ <> _) + } + + def showNode(p: RNode, pc: PrintContext): Cont = { + p match { + case RNil() => nil + case w: RWhitespace => { + pc.register(w) + nil + } + case RText(t: String) => { + val lw = pc.whitespace + pc.whitespace = None + showWhitespace(lw) <> text(t) + } + case t: RTrivia => { + if (t.hasComment()) { + pc.whitespace match { + case None => showTrivia(t, pc) + case Some(_) => showTrivia(t.trimmedTw(), pc) + } + } else { + nil + } + } + case RGroup(l: List[RNode]) => group(showList(l, pc)) + case RNest(l: List[RNode]) => nest(defaultIndent, showList(l, pc)) + } + } + + def showList(p: List[RNode], pc: PrintContext): Cont = { + println(s"${p}") + var reformatted = nil + for (n <- p) { + reformatted = reformatted <> showNode(n, pc) + } + reformatted + } + val pc = new PrintContext() val list = show2(p).filter(!_.isNil) - println(s"List: ${list}") - super.pretty(defaultWidth, showList(list)) + super.pretty(defaultWidth, showList(list, pc)) } def showOption2[T <: Any](n: Option[T])(implicit ctx: ReformatterContext2): List[RNode] = { @@ -472,7 +592,7 @@ object ReformatPrettyPrinter2 extends ReformatPrettyPrinterBase { val trivia = ctx.getTrivia(r.pos, updatePos); - trivia ::: r.reformat2(ctx) + List(trivia) ::: r.reformat2(ctx) } def showAny2(n: Any)(implicit ctx: ReformatterContext2): List[RNode] = { From c2b3033402afa86a8c0e57c9f50cd05002ecc9e6 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Fri, 22 Nov 2024 16:18:09 +0100 Subject: [PATCH 26/47] First working version, more or less back to where we started --- .../scala/viper/silver/parser/ParseAst.scala | 337 +++++++------- .../viper/silver/parser/ParseAstKeyword.scala | 44 +- .../silver/parser/ReformatPrettyPrinter.scala | 430 ++++-------------- .../silver/plugin/ParserPluginTemplate.scala | 9 +- .../standard/adt/AdtPASTExtension.scala | 22 +- .../PredicateInstancePASTExtension.scala | 2 +- .../standard/refute/RefutePASTExtension.scala | 2 +- .../smoke/UnreachablePASTExtension.scala | 2 +- .../TerminationPASTExtension.scala | 12 +- 9 files changed, 285 insertions(+), 575 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 0fad37ee9..020a4b308 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -17,10 +17,14 @@ import viper.silver.ast.utility.Visitor import viper.silver.ast.utility.rewriter.{HasExtraValList, HasExtraVars, Rewritable, StrategyBuilder} import viper.silver.ast.{Exp, Member, NoPosition, SourcePosition, Stmt, Type} import viper.silver.parser.PSymOp.{EqEq, Iff, Implies} +import viper.silver.parser.RGroup.rg +import viper.silver.parser.RLine.rl import viper.silver.parser.RLineBreak.rlb +import viper.silver.parser.RNest.rne import viper.silver.parser.RNil.rn +import viper.silver.parser.RSpace.rs import viper.silver.parser.RText.rt -import viper.silver.parser.ReformatPrettyPrinter2.{show2, showAnnotations2, showBody2, showPresPosts2, showReturns2} +import viper.silver.parser.ReformatPrettyPrinter.{show, showAnnotations, showBody, showPresPosts, showReturns} import viper.silver.parser.TypeHelper._ import viper.silver.verifier.ParseReport @@ -243,9 +247,7 @@ trait PIdentifier extends PLeaf { } case class PIdnDef(name: String)(val pos: (Position, Position)) extends PNode with PIdentifier { - override def reformat(implicit ctx: ReformatterContext): Cont = text(name) - - override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = rt(name) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt(name) } trait PIdnUse extends PNode with PIdentifier { @@ -296,7 +298,7 @@ case class PIdnUseExp(name: String)(val pos: (Position, Position)) extends PIdnU override def rename(newName: String) = PIdnUseExp(newName)(pos) - override def reformatExp(implicit ctx: ReformatterContext): Cont = text(name) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = rt(name) } case class PIdnRef[T <: PDeclarationInner](name: String)(val pos: (Position, Position))(implicit val ctag: scala.reflect.ClassTag[T]) extends PIdnUseName[T] { override def rename(newName: String): PIdnUse = PIdnRef(newName)(pos) @@ -312,7 +314,7 @@ case class PIdnRef[T <: PDeclarationInner](name: String)(val pos: (Position, Pos } override def getExtraVals: Seq[Any] = Seq(pos, ctag) - override def reformat(implicit ctx: ReformatterContext): Cont = name + override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt(name) } case class PVersionedIdnUseExp(name: String, version: String, separator: String = "@")(val pos: (Position, Position)) extends PIdnUseName[PTypedVarDecl] with PExp { @@ -330,7 +332,7 @@ case class PVersionedIdnUseExp(name: String, version: String, separator: String assert(typ.isGround) } - override def reformatExp(implicit ctx: ReformatterContext): Cont = text(versionedName) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = rt(versionedName) } /////////////////////////////////////////////////////////////////////////// @@ -340,7 +342,7 @@ trait PAnyFormalArgDecl extends PNode with PUnnamedTypedDeclaration with PPretty /** The declaration of an argument to a domain function. Not a `PDeclaration` as it will never clash. */ case class PDomainFunctionArg(name: Option[PIdnDef], c: Option[PSym.Colon], typ: PType)(val pos: (Position, Position)) extends PAnyFormalArgDecl { - override def reformat(implicit ctx: ReformatterContext): Cont = showOption(name) <> showOption(c) <+@> show(typ) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = showOption(name) <> showOption(c) <+> show(typ) } object PDomainFunctionArg { def apply(d: PIdnTypeBinding): PDomainFunctionArg = PDomainFunctionArg(Some(d.idndef), Some(d.c), d.typ)(d.pos) @@ -364,28 +366,28 @@ sealed trait PAssignableVarDecl extends PTypedVarDecl /** Any argument to a method, function or predicate. */ case class PFormalArgDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAnyFormalArgDecl with PTypedVarDecl with PMemberDeclaration with PMemberUniqueDeclaration { - override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <> show(c) <+> show(typ) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(idndef) <> show(c) <+> show(typ) } object PFormalArgDecl { def apply(d: PIdnTypeBinding): PFormalArgDecl = PFormalArgDecl(d.idndef, d.c, d.typ)(d.pos) } /** The return arguments of methods. */ case class PFormalReturnDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAssignableVarDecl with PMemberDeclaration with PMemberUniqueDeclaration { - override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <> show(c) <+> show(typ) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(idndef) <> show(c) <+> show(typ) } object PFormalReturnDecl { def apply(d: PIdnTypeBinding): PFormalReturnDecl = PFormalReturnDecl(d.idndef, d.c, d.typ)(d.pos) } case class PLogicalVarDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PTypedVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { - override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <> show(c) <+> show(typ) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(idndef) <> show(c) <+> show(typ) } object PLogicalVarDecl { def apply(d: PIdnTypeBinding): PLogicalVarDecl = PLogicalVarDecl(d.idndef, d.c, d.typ)(d.pos) } /** Declaration of a local variable. */ case class PLocalVarDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Position, Position)) extends PAssignableVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { - override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <> show(c) <+> show(typ) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(idndef) <> show(c) <+> show(typ) } object PLocalVarDecl { def apply(d: PIdnTypeBinding): PLocalVarDecl = PLocalVarDecl(d.idndef, d.c, d.typ)(d.pos) @@ -395,7 +397,7 @@ case class PFieldDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (Posi override def annotations = decl.toSeq.flatMap(_.annotations) override def pretty = s"${idndef.pretty}: ${typ.pretty}" - override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <> show(c) <+> show(typ) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(idndef) <> show(c) <+> show(typ) } object PFieldDecl { def apply(d: PIdnTypeBinding): PFieldDecl = PFieldDecl(d.idndef, d.c, d.typ)(d.pos) @@ -437,7 +439,7 @@ case class PPrimitiv[T <: PKeywordType](name: PReserved[T])(val pos: (Position, override def pretty = name.pretty - override def reformat(implicit ctx: ReformatterContext): Cont = show(name) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(name) } case class PDomainType(domain: PIdnRef[PTypeDeclaration], args: Option[PDelimited.Comma[PSym.Bracket, PType]])(val pos: (Position, Position)) extends PGenericType with HasExtraVars { @@ -487,7 +489,7 @@ case class PDomainType(domain: PIdnRef[PTypeDeclaration], args: Option[PDelimite override def copyExtraVars(from: Any): Unit = this.kind = from.asInstanceOf[PDomainType].kind - override def reformat(implicit ctx: ReformatterContext): Cont = show(domain) <> showOption(args) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(domain) <> showOption(args) } object PDomainTypeKinds { @@ -581,21 +583,21 @@ case class PSeqType(seq: PKw.Seq, elementType: PGrouped[PSym.Bracket, PType])(va override val genericName = "Seq" override def update(newType: PType) = copy(elementType = elementType.update(newType))(pos) - override def reformat(implicit ctx: ReformatterContext): Cont = show(seq) <> show(elementType) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(seq) <> show(elementType) } case class PSetType(set: PKw.Set, elementType: PGrouped[PSym.Bracket, PType])(val pos: (Position, Position)) extends PType with PGenericCollectionType { override val genericName = "Set" override def update(newType: PType) = copy(elementType = elementType.update(newType))(pos) - override def reformat(implicit ctx: ReformatterContext): Cont = show(set) <> show(elementType) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(set) <> show(elementType) } case class PMultisetType(multiset: PKw.Multiset, elementType: PGrouped[PSym.Bracket, PType])(val pos: (Position, Position)) extends PType with PGenericCollectionType { override val genericName = "Multiset" override def update(newType: PType) = copy(elementType = elementType.update(newType))(pos) - override def reformat(implicit ctx: ReformatterContext): Cont = show(multiset) <> show(elementType) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(multiset) <> show(elementType) } case class PMapType(map: PKw.Map, typ: PGrouped[PSym.Bracket, PPairArgument[PType, PType]])(val pos: (Position, Position)) extends PType with PGenericType { @@ -613,7 +615,7 @@ case class PMapType(map: PKw.Map, typ: PGrouped[PSym.Bracket, PPairArgument[PTyp override def withTypeArguments(s: Seq[PType]): PMapType = copy(typ = typ.update(PPairArgument(s(0), typ.inner.c, s(1))(typ.inner.pos)))(pos) - override def reformat(implicit ctx: ReformatterContext): Cont = show(map) <> show(typ) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(map) <> show(typ) } /** Exists temporarily after parsing and is replaced with @@ -626,7 +628,7 @@ case class PMacroType(use: PCall) extends PType { override def substitute(ts: PTypeSubstitution): PType = ??? override def subNodes: Seq[PType] = ??? - override def reformat(implicit ctx: ReformatterContext): Cont = show(use) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(use) } /** Type used for internal nodes (e.g. typing predicate accesses) - should not be @@ -642,28 +644,28 @@ sealed trait PInternalType extends PType { case class PUnknown() extends PInternalType { override def isValidOrUndeclared = false override def pretty = "" - override def reformat(implicit ctx: ReformatterContext): Cont = pretty + override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt(pretty) } case class PBoolImpureType() extends PInternalType { override def isValidOrUndeclared = true override def isPure: Boolean = false override def pretty = "" - override def reformat(implicit ctx: ReformatterContext): Cont = pretty + override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt(pretty) } case class PBoolWandType() extends PInternalType { override def isValidOrUndeclared = true override def isPure: Boolean = false override def umbrella: Option[PType] = Some(TypeHelper.Impure) override def pretty = "" - override def reformat(implicit ctx: ReformatterContext): Cont = pretty + override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt(pretty) } case class PBoolPredicateType() extends PInternalType { override def isValidOrUndeclared = true override def isPure: Boolean = false override def umbrella: Option[PType] = Some(TypeHelper.Impure) override def pretty = "" - override def reformat(implicit ctx: ReformatterContext): Cont = pretty + override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt(pretty) } /** The type of a `PIdnUse` which refers to a function. Ensures that we get a @@ -679,12 +681,12 @@ case class PFunctionType(argTypes: Seq[PType], resultType: PType) extends PInter s"$argsPretty: ${resultType.pretty}" } - override def reformat(implicit ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { (if (argTypes.isEmpty) - text("()") + rt("()") else - text("(") <> argTypes.map(show(_)).reduce(_ <> ", " <> _) <> text(")")) <> - text(": ") <> show(resultType) + rt("(") <> argTypes.map(show(_)).reduce(_ <> rt(", ") <> _) <> rt(")")) <> + rt(": ") <> show(resultType) } } @@ -716,13 +718,13 @@ trait PExp extends PNode with PPrettySubnodes with ReformattableExpression { // Note: We override the `reformat` for all expressions here, classes implementing this trait // should not override it. Instead, they should implement the `reformatExp` method. - override def reformat(implicit ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { // Unfortunately, we cannot just show exp.brackets, because then we end up in an // endless recursion. So instead, we need to add them manually. brackets match { case Some(b) => { if (b.l.isInstanceOf[PSym.Brace]) { - nest(defaultIndent, group(show(b.l) <@> this.reformatExp(ctx) <@> show(b.r))) + rne(rg(show(b.l) <@> this.reformatExp(ctx) <@> show(b.r))) } else { show(b.l) <> this.reformatExp(ctx) <> show(b.r) } @@ -736,7 +738,7 @@ case class PAnnotatedExp(annotation: PAnnotation, e: PExp)(val pos: (Position, P override def typeSubstitutions: collection.Seq[PTypeSubstitution] = e.typeSubstitutions override def forceSubstitution(ts: PTypeSubstitution): Unit = e.forceSubstitution(ts) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(annotation) <@@> show(e) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(annotation) <-> show(e) } trait PSubstitutionMap[S <: PSubstitutionMap[S]] { @@ -1046,8 +1048,8 @@ case class PCall(idnref: PIdnRef[PCallable], callArgs: PDelimited.Comma[PSym.Par args.foreach(_.forceSubstitution(ts)) } - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(idnref) <> - show(callArgs) <> typeAnnotated.map(e => show(e._1) <+> show(e._2)).getOrElse(nil) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(idnref) <> + show(callArgs) <> typeAnnotated.map(e => show(e._1) <+> show(e._2)).getOrElse(rn) } class PBinExp(val left: PExp, val op: PReserved[PBinaryOp], val right: PExp)(val pos: (Position, Position)) extends POpApp { @@ -1078,12 +1080,12 @@ class PBinExp(val left: PExp, val op: PReserved[PBinaryOp], val right: PExp)(val override def hashCode(): Int = viper.silver.utility.Common.generateHashCode(left, op.rs.operator, right) override def toString(): String = s"PBinExp($left,$op,$right)" - override def reformatExp(implicit ctx: ReformatterContext): Cont = { + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = { op.rs match { // Those operators look a bit better if they stick on the previous line case Iff | Implies | EqEq => - group(show(left) <+> show(op) <> nest(defaultIndent, show(right, SLine()))) - case _ => group(show(left) <@> show(op) <+> show(right)) + rg(show(left) <+> show(op) <> rne(rl <> show(right))) + case _ => rg(show(left) <@> show(op) <+> show(right)) } } @@ -1102,7 +1104,7 @@ case class PUnExp(op: PReserved[PUnaryOp], exp: PExp)(val pos: (Position, Positi override val args = Seq(exp) override val signatures = op.rs.signatures - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> show(exp) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <> show(exp) } case class PCondExp(cond: PExp, q: PSymOp.Question, thn: PExp, c: PSymOp.Colon, els: PExp)(val pos: (Position, Position)) extends POpApp { @@ -1111,9 +1113,9 @@ case class PCondExp(cond: PExp, q: PSymOp.Question, thn: PExp, c: PSymOp.Colon, Map(POpApp.pArgS(0) -> Bool, POpApp.pArgS(2) -> POpApp.pArg(1), POpApp.pResS -> POpApp.pArg(1)) ) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(cond) <+> show(q) <> - nest(defaultIndent, group(show(thn, SLine()) <+> - show(c) <> group(show(els, SLine())))) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(cond) <+> show(q) <> + rne(rg(rl <> show(thn) <+> + show(c) <> rg(rl <> show(els)))) } // Simple literals @@ -1131,11 +1133,11 @@ case class PIntLit(i: BigInt)(val pos: (Position, Position)) extends PSimpleLite typ = Int override def display = i.toString() - override def reformatExp(implicit ctx: ReformatterContext): Cont = text(i.toString) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = rt(i.toString) } case class PResultLit(result: PKw.Result)(val pos: (Position, Position)) extends PSimpleLiteral { - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(result) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(result) } case class PBoolLit(keyword: PReserved[PKeywordConstant])(val pos: (Position, Position)) extends PConstantLiteral { @@ -1145,13 +1147,13 @@ case class PBoolLit(keyword: PReserved[PKeywordConstant])(val pos: (Position, Po } typ = Bool - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) } case class PNullLit(keyword: PKw.Null)(val pos: (Position, Position)) extends PConstantLiteral { typ = Ref - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) } sealed trait PHeapOpApp extends POpApp @@ -1172,7 +1174,7 @@ case class PFieldAccess(rcv: PExp, dot: PSymOp.Dot, idnref: PIdnRef[PFieldDecl]) case _ => List() } - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(rcv) <> show(dot) <> show(idnref) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(rcv) <> show(dot) <> show(idnref) } case class PUnfolding(unfolding: PKwOp.Unfolding, acc: PAccAssertion, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { @@ -1180,7 +1182,7 @@ case class PUnfolding(unfolding: PKwOp.Unfolding, acc: PAccAssertion, in: PKwOp. override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Predicate, POpApp.pResS -> POpApp.pArg(1))) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(unfolding) <+> show(acc) <+> show(in) <> nest(defaultIndent, group(show(exp, SLine()))) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(unfolding) <+> show(acc) <+> show(in) <> rne(rg(rl <> show(exp))) } case class PApplying(applying: PKwOp.Applying, wand: PExp, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { @@ -1188,7 +1190,7 @@ case class PApplying(applying: PKwOp.Applying, wand: PExp, in: PKwOp.In, exp: PE override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Wand, POpApp.pResS -> POpApp.pArg(1))) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(applying) <+> show(wand) <+> show(in) <> nest(defaultIndent, group(show(exp, SLine()))) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(applying) <+> show(wand) <+> show(in) <> rne(rg(rl <> show(exp))) } case class PAsserting(asserting: PKwOp.Asserting, a: PExp, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { @@ -1196,9 +1198,9 @@ case class PAsserting(asserting: PKwOp.Asserting, a: PExp, in: PKwOp.In, exp: PE override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Impure, POpApp.pResS -> POpApp.pArg(1))) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(asserting) <+> - nest(defaultIndent, group(show(a, SLine()))) <+> - show(in) <> nest(defaultIndent, group(show(exp, SLine()))) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(asserting) <+> + rne(rg(rl <> show(a))) <+> + show(in) <> rne(rg(rl <> show(exp))) } sealed trait PBinder extends PExp with PScope { @@ -1220,7 +1222,7 @@ sealed trait PBinder extends PExp with PScope { case class PTrigger(exp: PDelimited.Comma[PSym.Brace, PExp])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { override def pretty = exp.pretty - override def reformat(implicit ctx: ReformatterContext): Cont = show(exp) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(exp) } sealed trait PQuantifier extends PBinder { @@ -1232,21 +1234,21 @@ sealed trait PQuantifier extends PBinder { } case class PExists(keyword: PKw.Exists, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier { - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <+> show(vars) <+> - show(c) <> nest(defaultIndent, group(line <> (showSeq(triggers) <+@> show(body)))) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <+> show(vars) <+> + show(c) <> rne(rg(rl <> (showSeq(triggers) <+> show(body)))) } case class PForall(keyword: PKw.Forall, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier { - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <+> show(vars) <+> - show(c) <> nest(defaultIndent, group(line <> group(showSeq(triggers) <+@> show(body)))) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <+> show(vars) <+> + show(c) <> rne(rg(rl <> rg(showSeq(triggers) <+> show(body)))) } case class PForPerm(keyword: PKw.Forperm, vars: PDelimited[PLogicalVarDecl, PSym.Comma], accessRes: PGrouped[PSym.Bracket, PResourceAccess], c: PSym.ColonColon, body: PExp)(val pos: (Position, Position)) extends PQuantifier { val triggers: Seq[PTrigger] = Seq() - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <+> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <+> show(vars) <+> show(accessRes) <+> show(c) <> - nest(defaultIndent, group(show(body, SLine()))) + rne(rg(rl <> show(body))) } /* Let-expressions `let x == e1 in e2` are represented by the nested structure @@ -1270,8 +1272,8 @@ case class PLet(l: PKwOp.Let, variable: PIdnDef, eq: PSymOp.EqEq, exp: PGrouped. typ = nestedScope.body.typ } - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(l) <+> show(variable) <+> - show(eq) <+> show(exp) <+> show(in) <> group(show(nestedScope, SLine())) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(l) <+> show(variable) <+> + show(eq) <+> show(exp) <+> show(in) <> rg(rl <> show(nestedScope)) } case class PLetNestedScope(body: PExp)(val pos: (Position, Position)) extends PTypedVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { @@ -1279,7 +1281,7 @@ case class PLetNestedScope(body: PExp)(val pos: (Position, Position)) extends PT override def idndef: PIdnDef = outerLet.variable override def typ: PType = outerLet.exp.inner.typ - override def reformat(implicit ctx: ReformatterContext): Cont = show(body) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(body) } // [in,ex] @@ -1291,20 +1293,20 @@ case class PInhaleExhaleExp(l: PSymOp.LBracket, in: PExp, c: PSymOp.Comma, ex: P Map(POpApp.pArgS(0) -> Impure, POpApp.pArgS(1) -> Impure, POpApp.pResS -> Impure), ) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(l) <> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(l) <> show(in) <> show(c) <+> show(ex) <> show(r) } case class PNoPerm(keyword: PKw.None)(val pos: (Position, Position)) extends PConstantLiteral { typ = Perm - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) } case class PFullPerm(keyword: PKw.Write)(val pos: (Position, Position)) extends PConstantLiteral { typ = Perm - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) } object PFullPerm { def implied(): PFullPerm = PFullPerm(PReserved(PKw.Write)(NoPosition, NoPosition))(NoPosition, NoPosition) @@ -1313,13 +1315,13 @@ object PFullPerm { case class PWildcard(keyword: PKw.Wildcard)(val pos: (Position, Position)) extends PConstantLiteral { typ = Perm - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) } case class PEpsilon(keyword: PKw.Epsilon)(val pos: (Position, Position)) extends PConstantLiteral { typ = Perm - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) } trait PCallKeyword extends POpApp { @@ -1332,14 +1334,14 @@ case class PCurPerm(op: PKwOp.Perm, res: PGrouped.Paren[PResourceAccess])(val po Map(POpApp.pResS -> Perm) ) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <+> show(res) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <+> show(res) } case class PPairArgument[+T, +U](first: T, c: PSym.Comma, second: U)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(implicit ctx: ReformatterContext): Cont = showAny(first) <> show(c) <+> showAny(second) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAny(first) <> show(c) <+> showAny(second) } case class PMaybePairArgument[+T, +U](first: T, second: Option[(PSym.Comma, U)])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(implicit ctx: ReformatterContext): Cont = showAny(first) <> second.map(a => show(a._1) <+> showAny(a._2)).getOrElse(nil) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAny(first) <> second.map(a => show(a._1) <+> showAny(a._2)).getOrElse(rn) } sealed trait PAccAssertion extends PExp { @@ -1356,7 +1358,7 @@ case class PAccPred(op: PKwOp.Acc, amount: PGrouped.Paren[PMaybePairArgument[PLo def perm = amount.inner.second.map(_._2).getOrElse(PFullPerm.implied()) override val args = Seq(loc, perm) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> show(amount) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <> show(amount) } case class POldExp(op: PKwOp.Old, label: Option[PGrouped[PSym.Bracket, Either[PKw.Lhs, PIdnRef[PLabel]]]], e: PGrouped.Paren[PExp])(val pos: (Position, Position)) extends PCallKeyword with PHeapOpApp { @@ -1364,7 +1366,7 @@ case class POldExp(op: PKwOp.Old, label: Option[PGrouped[PSym.Bracket, Either[PK override def requirePure = args override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pResS -> POpApp.pArg(0))) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> showOption(label) <> show(e) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <> showOption(label) <> show(e) } case class PDebugLabelledOldExp(op: PKwOp.Old, label: PVersionedIdnUseExp, e: PExp)(val pos: (Position, Position)) extends PCallKeyword with PHeapOpApp { @@ -1374,7 +1376,7 @@ case class PDebugLabelledOldExp(op: PKwOp.Old, label: PVersionedIdnUseExp, e: PE override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pResS -> POpApp.pArg(0))) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> show(label) <> show(e) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <> show(label) <> show(e) } sealed trait PCollectionLiteral extends PCallKeyword { @@ -1422,11 +1424,11 @@ sealed trait PSeqLiteral extends PCollectionLiteral { } case class PEmptySeq(op: PKwOp.Seq, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PSeqLiteral with PEmptyCollectionLiteral { - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> showOption(pAnnotatedType) <> show(callArgs) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <> showOption(pAnnotatedType) <> show(callArgs) } case class PExplicitSeq(op: PKwOp.Seq, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PSeqLiteral with PExplicitCollectionLiteral { - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> show(callArgs) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <> show(callArgs) } // [low..high) @@ -1436,7 +1438,7 @@ case class PRangeSeq(l: PSymOp.LBracket, low: PExp, ds: PSymOp.DotDot, high: PEx override val signatures: List[PTypeSubstitution] = List( Map(POpApp.pArgS(0) -> Int, POpApp.pArgS(1) -> Int, POpApp.pResS -> MakeSeq(Int))) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(l) <> show(low) <> show(ds) <> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(l) <> show(low) <> show(ds) <> show(high) <> show(r) } @@ -1452,7 +1454,7 @@ case class PLookup(base: PExp, l: PSymOp.LBracket, idx: PExp, r: PSymOp.RBracket Map(POpApp.pArgS(0) -> MakeMap(keyType, POpApp.pRes)) ) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(base) <> show(l) <> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(base) <> show(l) <> show(idx) <> show(r) } @@ -1469,7 +1471,7 @@ case class PSeqSlice(seq: PExp, l: PSymOp.LBracket, s: Option[PExp], d: PSymOp.D case (None, None) => Map() })) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(seq) <> show(l) <> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(seq) <> show(l) <> showOption(s) <> show(d) <> showOption(e) <> show(r) } @@ -1485,7 +1487,7 @@ case class PUpdate(base: PExp, l: PSymOp.LBracket, key: PExp, a: PSymOp.Assign, Map(POpApp.pArgS(0) -> MakeMap(keyType, elementType), POpApp.pResS -> MakeMap(keyType, elementType)) ) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(base) <> show(l) <> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(base) <> show(l) <> show(key) <+> show(a) <+> show(value) <> show(r) } @@ -1504,7 +1506,7 @@ case class PSize(l: PSymOp.Or, seq: PExp, r: PSymOp.Or)(val pos: (Position, Posi Map(POpApp.pArgS(0) -> MakeMap(keyType, elementType), POpApp.pResS -> Int) ) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(l) <> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(l) <> show(seq) <> show(r) } @@ -1513,12 +1515,12 @@ sealed trait PSetLiteral extends PCollectionLiteral { } case class PEmptySet(op: PKwOp.Set, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PSetLiteral with PEmptyCollectionLiteral { - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <> showOption(pAnnotatedType) <> show(callArgs) } case class PExplicitSet(op: PKwOp.Set, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PSetLiteral with PExplicitCollectionLiteral { - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> show(callArgs) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <> show(callArgs) } sealed trait PMultiSetLiteral extends PCollectionLiteral { @@ -1526,12 +1528,12 @@ sealed trait PMultiSetLiteral extends PCollectionLiteral { } case class PEmptyMultiset(op: PKwOp.Multiset, pAnnotatedType: Option[PGrouped[PSym.Bracket, PType]], callArgs: PDelimited.Comma[PSym.Paren, Nothing])(val pos: (Position, Position)) extends PMultiSetLiteral with PEmptyCollectionLiteral { - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <> showOption(pAnnotatedType) <> show(callArgs) } case class PExplicitMultiset(op: PKwOp.Multiset, callArgs: PDelimited.Comma[PSym.Paren, PExp])(val pos: (Position, Position)) extends PMultiSetLiteral with PExplicitCollectionLiteral { - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <> show(callArgs) } @@ -1563,7 +1565,7 @@ case class PEmptyMap(op: PKwOp.Map, pAnnotatedType: Option[PGrouped[PSym.Bracket def explicitType: Option[(PType, PType)] = pAnnotatedType.map(t => (t.inner.first, t.inner.second)) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <> showOption(pAnnotatedType) <> show(callArgs) } @@ -1578,7 +1580,7 @@ case class PExplicitMap(op: PKwOp.Map, callArgs: PDelimited.Comma[PSym.Paren, PM }.toMap ) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(op) <> show(callArgs) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(op) <> show(callArgs) } /** @@ -1591,7 +1593,7 @@ case class PMaplet(key: PExp, a: PSymOp.Assign, value: PExp)(val pos: (Position, POpApp.pResS -> MakeMap(POpApp.pArg(0), POpApp.pArg(1)) )) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(key) <+> show(a) <+> show(value) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(key) <+> show(a) <+> show(value) } case class PMapDomain(keyword: PKwOp.Domain, base: PGrouped.Paren[PExp])(val pos: (Position, Position)) extends POpApp { @@ -1606,7 +1608,7 @@ case class PMapDomain(keyword: PKwOp.Domain, base: PGrouped.Paren[PExp])(val pos POpApp.pResS -> MakeSet(keyType) )) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <> show(base) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <> show(base) } case class PMapRange(keyword: PKwOp.Range, base: PGrouped.Paren[PExp])(val pos: (Position, Position)) extends POpApp { @@ -1621,7 +1623,7 @@ case class PMapRange(keyword: PKwOp.Range, base: PGrouped.Paren[PExp])(val pos: POpApp.pResS -> MakeSet(valueType) )) - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <> show(base) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <> show(base) } @@ -1630,15 +1632,13 @@ case class PMapRange(keyword: PKwOp.Range, base: PGrouped.Paren[PExp])(val pos: trait PStmt extends PNode with PPrettySubnodes case class PAnnotatedStmt(annotation: PAnnotation, stmt: PStmt)(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(annotation) <@@> show(stmt) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(annotation) <-> show(stmt) } case class PSeqn(ss: PDelimited.Block[PStmt])(val pos: (Position, Position)) extends PStmt with PScope { override def pretty = ss.prettyLines - override def reformat(implicit ctx: ReformatterContext): Cont = show(ss) - - override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = show2(ss) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(ss) } /** @@ -1648,61 +1648,61 @@ case class PSeqn(ss: PDelimited.Block[PStmt])(val pos: (Position, Position)) ext * before translation. */ case class PMacroSeqn(ss: PDelimited.Block[PStmt])(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(ss) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(ss) } case class PFold(fold: PKw.Fold, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(fold) <+> show(e) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(fold) <+> show(e) } case class PUnfold(unfold: PKw.Unfold, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(unfold) <+> show(e) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(unfold) <+> show(e) } case class PPackageWand(pckg: PKw.Package, e: PExp, proofScript: Option[PSeqn])(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(pckg) <+> show(e) <+> + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(pckg) <+> show(e) <+> showOption(proofScript) } case class PApplyWand(apply: PKw.Apply, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(apply) <+> show(e) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(apply) <+> show(e) } case class PExhale(exhale: PKw.Exhale, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(exhale) <+> show(e) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(exhale) <+> show(e) } case class PAssert(assert: PKw.Assert, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(assert) <+> show(e) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(assert) <+> show(e) } case class PAssume(assume: PKw.Assume, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(assume) <+> show(e) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(assume) <+> show(e) } case class PInhale(inhale: PKw.Inhale, e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(inhale) <+> show(e) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(inhale) <+> show(e) } /** Can also represent a method call or statement macro with no `:=` when `targets` is empty. */ case class PAssign(targets: PDelimited[PExp with PAssignTarget, PSym.Comma], op: Option[PSymOp.Assign], rhs: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(targets) <+@> showOption(op) <+@> nest(defaultIndent, show(rhs)) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(targets) <+> showOption(op) <+> rne(show(rhs)) } sealed trait PIfContinuation extends PStmt case class PIf(keyword: PReserved[PKeywordIf], cond: PGrouped.Paren[PExp], thn: PSeqn, els: Option[PIfContinuation])(val pos: (Position, Position)) extends PStmt with PIfContinuation { - override def reformat(implicit ctx: ReformatterContext): Cont = show(keyword) <+> show(cond) <> - showBody(thn, false) <> els.map(showBody(_, false)).getOrElse(nil) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <+> show(cond) <> + showBody(thn, false) <> els.map(showBody(_, false)).getOrElse(rn) } case class PElse(k: PKw.Else, els: PSeqn)(val pos: (Position, Position)) extends PStmt with PIfContinuation { - override def reformat(implicit ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { show(k) <> showBody(els, false) } } case class PWhile(keyword: PKw.While, cond: PGrouped.Paren[PExp], invs: PDelimited[PSpecification[PKw.InvSpec], Option[PSym.Semi]], body: PSeqn)(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { show(keyword) <> show(cond) <+> showInvs(invs) <> showBody(body, !invs.isEmpty) } @@ -1711,36 +1711,36 @@ case class PWhile(keyword: PKw.While, cond: PGrouped.Paren[PExp], invs: PDelimit case class PVars(keyword: PKw.Var, vars: PDelimited[PLocalVarDecl, PSym.Comma], init: Option[(PSymOp.Assign, PExp)])(val pos: (Position, Position)) extends PStmt { def assign: Option[PAssign] = init map (i => PAssign(vars.update(vars.toSeq.map(_.toIdnUse)), Some(i._1), i._2)(pos)) - override def reformat(implicit ctx: ReformatterContext): Cont = + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <+> show(vars) <> - init.map(s => nest(defaultIndent, group(nil <+> show(s._1) <@> show(s._2)))).getOrElse(nil) + init.map(s => rne(rg(rs <> show(s._1) <@> show(s._2)))).getOrElse(rn) } case class PLabel(label: PKw.Label, idndef: PIdnDef, invs: PDelimited[PSpecification[PKw.InvSpec], Option[PSym.Semi]])(val pos: (Position, Position)) extends PStmt with PMemberDeclaration with PBackwardDeclaration { - override def reformat(implicit ctx: ReformatterContext): Cont = show(label) <+> show(idndef) <+> show(invs) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(label) <+> show(idndef) <+> show(invs) } case class PGoto(goto: PKw.Goto, target: PIdnRef[PLabel])(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(goto) <+> show(target) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(goto) <+> show(target) } // Should this be sealed? sealed trait PTypeDeclaration extends PDeclarationInner case class PTypeVarDecl(idndef: PIdnDef)(val pos: (Position, Position)) extends PMemberDeclaration with PTypeDeclaration with PPrettySubnodes { - override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(idndef) } case class PSkip()(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = text("") + override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt("") } case class PQuasihavoc(quasihavoc: PKw.Quasihavoc, lhs: Option[(PExp, PSymOp.Implies)], e: PExp)(val pos: (Position, Position)) extends PStmt { - override def reformat(implicit ctx: ReformatterContext): Cont = show(quasihavoc) <+@> showOption(lhs) <+@> show(e) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(quasihavoc) <+> showOption(lhs) <+> show(e) } case class PQuasihavocall(quasihavocall: PKw.Quasihavocall, vars: PDelimited[PLogicalVarDecl, PSym.Comma], colons: PSym.ColonColon, lhs: Option[(PExp, PSymOp.Implies)], e: PExp)(val pos: (Position, Position)) extends PStmt with PScope { - override def reformat(implicit ctx: ReformatterContext): Cont = show(quasihavocall) <+@> showOption(lhs) <+@> show(e) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(quasihavocall) <+> showOption(lhs) <+> show(e) } /* new(f1, ..., fn) or new(*) */ @@ -1748,7 +1748,7 @@ case class PNewExp(keyword: PKw.New, fields: PGrouped.Paren[Either[PSym.Star, PD override final val typeSubstitutions = Seq(PTypeSubstitution.id) def forceSubstitution(ts: PTypeSubstitution) = {} - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(keyword) <> show(fields) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <> show(fields) } sealed trait PScope extends PNode { @@ -1821,7 +1821,7 @@ trait PTypedDeclaration extends PUnnamedTypedDeclaration case class PBracedExp(e: PGrouped[PSym.Brace, PExp])(val pos: (Position, Position)) extends PNode { override def pretty = s" ${e.l.pretty}\n ${e.inner.pretty.replace("\n", "\n ")}\n${e.r.pretty}" - override def reformat(implicit ctx: ReformatterContext): Cont = show(e) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(e) } trait PCallable extends PDeclarationInner { @@ -1890,18 +1890,11 @@ case class PProgram(imported: Seq[PProgram], members: Seq[PMember])(val pos: (Po prefix + m + "\n\n" + i } - override def reformat(implicit ctx: ReformatterContext): Cont = { - if (members.isEmpty) - nil - else - members.zipWithIndex.map(e => show(e._1, if (e._2 == 0) SNil() else SLinebreak())).reduce((acc, n) => acc <> n) - } - - override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = { + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { if (members.isEmpty) rn else - members.zipWithIndex.map(e => (if (e._2 == 0) rn else rlb) <> show2(e._1)).reduce((acc, n) => acc <> n) + members.zipWithIndex.map(e => (if (e._2 == 0) rn else rlb) <> show(e._1)).reduce((acc, n) => acc <> n) } // Pretty print members in a specific order @@ -1925,16 +1918,16 @@ case class PImport(annotations: Seq[PAnnotation], imprt: PKw.Import, file: PStri var resolved: Option[Path] = None def declares = Nil - override def reformat(implicit ctx: ReformatterContext): Cont = show(imprt) <+> show(file) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(imprt) <+> show(file) } case class PDefineParam(idndef: PIdnDef)(val pos: (Position, Position)) extends PNode with PLocalDeclaration with PPrettySubnodes { - override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(idndef) } case class PDefine(annotations: Seq[PAnnotation], define: PKw.Define, idndef: PIdnDef, parameters: Option[PDelimited.Comma[PSym.Paren, PDefineParam]], body: PNode)(val pos: (FilePosition, FilePosition)) extends PSingleMember with PStmt with PNameAnalyserOpaque { - override def reformat(implicit ctx: ReformatterContext): Cont = { - showAnnotations(annotations) <@@> show(define) <+> show(idndef) <> showOption(parameters) <+> show(body) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { + showAnnotations(annotations) <-> show(define) <+> show(idndef) <> showOption(parameters) <+> show(body) } } @@ -1942,10 +1935,10 @@ case class PDomain(annotations: Seq[PAnnotation], domain: PKw.Domain, idndef: PI (val pos: (Position, Position)) extends PSingleMember with PTypeDeclaration with PPrettySubnodes { def typVarsSeq: Seq[PTypeVarDecl] = typVars.map(_.inner.toSeq).getOrElse(Nil) - override def reformat(implicit ctx: ReformatterContext): Cont = { - showAnnotations(annotations) <@@> show(domain) <+> + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { + showAnnotations(annotations) <-> show(domain) <+> show(idndef) <> showOption(typVars) <> - (if (interpretations.isEmpty) nil else nest(defaultIndent, showOption(interpretations, SLinebreak()))) <> + (if (interpretations.isEmpty) rn else rne(rlb <> showOption(interpretations))) <> showBody(members, !interpretations.isEmpty) } } @@ -1953,7 +1946,7 @@ case class PDomain(annotations: Seq[PAnnotation], domain: PKw.Domain, idndef: PI case class PDomainFunctionInterpretation(k: PKw.Interpretation, i: PStringLiteral)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { override def pretty = s"\n ${super.pretty}" - override def reformat(implicit ctx: ReformatterContext): Cont = show(k) <+> show(i) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(k) <+> show(i) } trait PDomainMember extends PScope { def domain: PDomain = getAncestor[PDomain].get @@ -1961,13 +1954,13 @@ trait PDomainMember extends PScope { case class PDomainFunction(annotations: Seq[PAnnotation], unique: Option[PKw.Unique], keyword: PKw.FunctionD, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PDomainFunctionArg], c: PSym.Colon, resultType: PType, interpretation: Option[PDomainFunctionInterpretation])(val pos: (Position, Position)) extends PSingleMember with PNoSpecsFunction with PDomainMember with PPrettySubnodes { override def body = None - override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> showOption(unique) <+@> + override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAnnotations(annotations) <-> showOption(unique) <+> show(keyword) <+> show(idndef) <+> show(args) <> show(c) <+> show(resultType) <+> showOption(interpretation) } case class PAxiom(annotations: Seq[PAnnotation], axiom: PKw.Axiom, idndef: Option[PIdnDef], exp: PBracedExp)(val pos: (Position, Position)) extends PDomainMember with PPrettySubnodes { - override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> show(axiom) <+> + override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAnnotations(annotations) <-> show(axiom) <+> showOption(idndef) <+> show(exp) } case class PDomainMembers(funcs: PDelimited[PDomainFunction, Option[PSym.Semi]], axioms: PDelimited[PAxiom, Option[PSym.Semi]])(val pos: (Position, Position), val original: PDomainMembers1) extends PNode { @@ -1979,31 +1972,31 @@ case class PDomainMembers(funcs: PDelimited[PDomainFunction, Option[PSym.Semi]], override def getExtraVals: Seq[Any] = Seq(pos, original) - override def reformat(implicit ctx: ReformatterContext): Cont = show(original) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(original) } case class PDomainInterpretation(name: PRawString, c: PSym.Colon, lit: PStringLiteral)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(implicit ctx: ReformatterContext): Cont = show(name) <> show(c) <+> show(lit) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(name) <> show(c) <+> show(lit) } case class PDomainInterpretations(k: PReserved[PKeywordLang], m: PDelimited.Comma[PSym.Paren, PDomainInterpretation])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { def interps: Map[String, String] = m.inner.toSeq.map(i => i.name.str -> i.lit.str).toMap - override def reformat(implicit ctx: ReformatterContext): Cont = show(k) <+> show(m) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(k) <+> show(m) } trait PDomainMember1 extends PNode with PPrettySubnodes case class PDomainFunction1(annotations: Seq[PAnnotation], unique: Option[PKw.Unique], function: PKw.FunctionD, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PDomainFunctionArg], c: PSym.Colon, typ: PType, interpretation: Option[PDomainFunctionInterpretation], s: Option[PSym.Semi])(val pos: (Position, Position)) extends PDomainMember1 { - override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> showOption(unique) <+@> - show(function) <+@> showOption(interpretation) <+> + override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAnnotations(annotations) <-> showOption(unique) <+> + show(function) <+> showOption(interpretation) <+> show(idndef) <> show(args) <> show(c) <+> show(typ) <+> showOption(s) } case class PAxiom1(annotations: Seq[PAnnotation], axiom: PKw.Axiom, idndef: Option[PIdnDef], exp: PBracedExp, s: Option[PSym.Semi])(val pos: (Position, Position)) extends PDomainMember1 { - override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> show(axiom) <+@> - showOption(idndef) <+@> show(exp) <> showOption(s) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAnnotations(annotations) <-> show(axiom) <+> + showOption(idndef) <+> show(exp) <> showOption(s) } case class PDomainMembers1(members: Seq[PDomainMember1])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(implicit ctx: ReformatterContext): Cont = if (members.isEmpty) nil else members.zipWithIndex - .map(m => if (m._2 == 0) show(m._1) else show(m._1, SLinebreak())) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = if (members.isEmpty) rn else members.zipWithIndex + .map(m => if (m._2 == 0) show(m._1) else rlb <> show(m._1)) .reduce(_ <> _) } @@ -2011,7 +2004,7 @@ case class PDomainMembers1(members: Seq[PDomainMember1])(val pos: (Position, Pos case class PFields(annotations: Seq[PAnnotation], field: PKw.Field, fields: PDelimited[PFieldDecl, PSym.Comma], s: Option[PSym.Semi])(val pos: (Position, Position)) extends PMember with PPrettySubnodes { override def declares: Seq[PGlobalDeclaration] = fields.toSeq - override def reformat(implicit ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { // println(s"PFields"); // println(s"---------------------------"); // println(s"annotation: ${annotation}"); @@ -2025,19 +2018,19 @@ case class PFields(annotations: Seq[PAnnotation], field: PKw.Field, fields: PDel case class PSpecification[+T <: PKw.Spec](k: PReserved[PKw.Spec], e: PExp)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { override def pretty: String = "\n " + super.pretty - override def reformat(implicit ctx: ReformatterContext): Cont = show(k) <+> show(e) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(k) <+> show(e) } case class PFunction(annotations: Seq[PAnnotation], keyword: PKw.Function, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PFormalArgDecl], c: PSym.Colon, resultType: PType, pres: PDelimited[PSpecification[PKw.PreSpec], Option[PSym.Semi]], posts: PDelimited[PSpecification[PKw.PostSpec], Option[PSym.Semi]], body: Option[PBracedExp]) (val pos: (Position, Position)) extends PSingleMember with PAnyFunction with PGlobalCallableNamedArgs with PPrettySubnodes { - override def reformat(implicit ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { // TODO: Add PFunctioNType println(s"PFunction"); println(s"---------------------------"); println(s"body ${body}"); - showAnnotations(annotations) <@@> show(keyword) <+> show(idndef) <> + showAnnotations(annotations) <-> show(keyword) <+> show(idndef) <> show(args) <> show(c) <+> show(resultType) <> - showPresPosts(pres, posts) <> body.map(showBody(_, !(pres.isEmpty && posts.isEmpty))).getOrElse(nil) + showPresPosts(pres, posts) <> body.map(showBody(_, !(pres.isEmpty && posts.isEmpty))).getOrElse(rn) } } @@ -2046,8 +2039,8 @@ case class PPredicate(annotations: Seq[PAnnotation], keyword: PKw.Predicate, idn override def c = PReserved.implied(PSym.Colon) override def resultType = Predicate - override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> show(keyword) <+> show(idndef) <> - show(args) <> body.map(showBody(_, false)).getOrElse(nil) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAnnotations(annotations) <-> show(keyword) <+> show(idndef) <> + show(args) <> body.map(showBody(_, false)).getOrElse(rn) } case class PMethod(annotations: Seq[PAnnotation], keyword: PKw.Method, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PFormalArgDecl], returns: Option[PMethodReturns], pres: PDelimited[PSpecification[PKw.PreSpec], Option[PSym.Semi]], posts: PDelimited[PSpecification[PKw.PostSpec], Option[PSym.Semi]], body: Option[PSeqn]) @@ -2055,19 +2048,14 @@ case class PMethod(annotations: Seq[PAnnotation], keyword: PKw.Method, idndef: P def formalReturns: Seq[PFormalReturnDecl] = returns.map(_.formalReturns.inner.toSeq).getOrElse(Nil) override def returnNodes = returns.toSeq - override def reformat(implicit ctx: ReformatterContext): Cont = { - showAnnotations(annotations) <@@> show(keyword) <+> show(idndef) <> show(args) <> showReturns(returns) <> - showPresPosts(pres, posts) <> body.map(showBody(_, !(returns.isEmpty && pres.isEmpty && posts.isEmpty))).getOrElse(nil) - } - - override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = { - showAnnotations2(annotations) <-> show2(keyword) <+> show2(idndef) <> show2(args) <> showReturns2(returns) <> - showPresPosts2(pres, posts) <> body.map(showBody2(_, !(returns.isEmpty && pres.isEmpty && posts.isEmpty))).getOrElse(rn) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { + showAnnotations(annotations) <-> show(keyword) <+> show(idndef) <> show(args) <> showReturns(returns) <> + showPresPosts(pres, posts) <> body.map(showBody(_, !(returns.isEmpty && pres.isEmpty && posts.isEmpty))).getOrElse(rn) } } case class PMethodReturns(k: PKw.Returns, formalReturns: PGrouped.Paren[PDelimited[PFormalReturnDecl, PSym.Comma]])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(implicit ctx: ReformatterContext): Cont = show(k) <+> show(formalReturns) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(k) <+> show(formalReturns) } /** @@ -2078,21 +2066,21 @@ case class PAnnotationsPosition(annotations: Seq[PAnnotation], pos: (FilePositio case class PAnnotation(at: PSym.At, key: PRawString, values: PGrouped.Paren[PDelimited[PStringLiteral, PSym.Comma]])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { override def pretty: String = super.pretty + "\n" - override def reformat(implicit ctx: ReformatterContext): Cont = show(at) <> show(key) <> show(values) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(at) <> show(key) <> show(values) } // Any unenclosed string (e.g. `hello`) case class PRawString(str: String)(val pos: (Position, Position)) extends PNode with PLeaf { override def display: String = str - override def reformat(implicit ctx: ReformatterContext): Cont = text(str) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt(str) } // Any enclosed string (e.g. `"hello"`) case class PStringLiteral(grouped: PGrouped[_, PRawString])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { def str: String = grouped.inner.str - override def reformat(implicit ctx: ReformatterContext): Cont = show(grouped) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(grouped) } trait PExtender extends PNode { @@ -2112,29 +2100,12 @@ trait PExtender extends PNode { } // Trivia (comments, whitespaces) -trait Trivia extends FastPrettyPrinterBase { - def display: Cont -} - -case class POther() extends Trivia { - override def display: Cont = text("") -} - -case class PSpace() extends Trivia { - override def display: Cont = space -} - -case class PNewLine() extends Trivia { - override def display: Cont = linebreak -} +trait Trivia +case class POther() extends Trivia +case class PSpace() extends Trivia +case class PNewLine() extends Trivia case class PComment(inner: String, block: Boolean) extends Trivia { - def display: Cont = if (block) { - text("/*") <> inner <> text("*/") - } else { - text("//") <> text(inner) - } - def str: String = if (block) { "/*" + inner + "*/" } else { diff --git a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala index 8bd28aa4e..7ddc23611 100644 --- a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala +++ b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala @@ -15,7 +15,6 @@ import viper.silver.parser.RNil.rn import viper.silver.parser.RSpace.rs import viper.silver.parser.RText.rt import viper.silver.parser.ReformatPrettyPrinter.{show, showAny} -import viper.silver.parser.ReformatPrettyPrinter2.{show2, showAny2} import viper.silver.parser.TypeHelper._ trait PReservedString { @@ -31,9 +30,7 @@ case class PReserved[+T <: PReservedString](rs: T)(val pos: (Position, Position) override def display = rs.display def token = rs.token - override def reformat(implicit ctx: ReformatterContext): Cont = text(token) - - override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = rt(token) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt(token) } object PReserved { def implied[T <: PReservedString](rs: T): PReserved[T] = PReserved(rs)(NoPosition, NoPosition) @@ -47,33 +44,18 @@ case class PGrouped[G <: PSym.Group, +T](l: PReserved[G#L], inner: T, r: PReserv s"${l.pretty}${iPretty}${r.pretty}" } - override def reformat(implicit ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { if (l.rs.isInstanceOf[Brace]) { val left = show(l); val inner_ = showAny(inner); val right = show(r); - if (inner_ == nil) { - left <> right - } else { - left <> nest(defaultIndent, line <> inner_) <> line <> right - } - } else { - show(l) <> nest(defaultIndent, showAny(inner)) <> show(r) - } - } - - override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = { - if (l.rs.isInstanceOf[Brace]) { - val left = show2(l); - val inner_ = showAny2(inner); - val right = show2(r); if (inner_.forall(_.isNil)) { left <> right } else { left <> rne(rl <> inner_) <> rl <> right } } else { - show2(l) <> rne(showAny2(inner)) <> show2(r) + show(l) <> rne(showAny(inner)) <> show(r) } } } @@ -129,28 +111,16 @@ class PDelimited[+T, +D]( override def hashCode(): Int = viper.silver.utility.Common.generateHashCode(first, inner, end) override def toString(): String = s"PDelimited($first,$inner,$end)" - override def reformat(implicit ctx: ReformatterContext): Cont = { - val separator = delimiters.headOption match { - case Some(p: PSym.Comma) => SSpace() - case None => SNil() - case _ => SLinebreak() - }; - - showAny(first) <@@@> - inner.foldLeft(nil)((acc, b) => acc <@@@> showAny(b._1) <@@@> showAny(b._2, separator)) <@@@> - showAny(end) - } - - override def reformat2(implicit ctx: ReformatterContext2): List[RNode] = { + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { val separator = delimiters.headOption match { case Some(p: PSym.Comma) => rs case None => rn case _ => rlb }; - showAny2(first) <> - inner.foldLeft(rn)((acc, b) => acc <> showAny2(b._1) <> separator <> showAny2(b._2)) <> - showAny2(end) + showAny(first) <> + inner.foldLeft(rn)((acc, b) => acc <> showAny(b._1) <> separator <> showAny(b._2)) <> + showAny(end) } } diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 1f06abf89..20cec341d 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -3,7 +3,7 @@ package viper.silver.parser import fastparse.Parsed import viper.silver.ast import viper.silver.ast.HasLineColumn -import viper.silver.ast.pretty.{Call, PrettyPrintPrimitives} +import viper.silver.ast.pretty.FastPrettyPrinterBase import viper.silver.parser.FastParserCompanion.programTrivia import viper.silver.parser.RLine.rl import viper.silver.parser.RLineBreak.rlb @@ -16,10 +16,8 @@ import scala.collection.mutable.ArrayBuffer trait RNode { def isNil: Boolean } - -trait RWhitespace extends RNode - trait RCommentFragment +trait RWhitespace extends RNode with RCommentFragment case class RNil() extends RNode { override def isNil: Boolean = true @@ -50,8 +48,13 @@ case class RTrivia(l: List[RCommentFragment]) extends RNode { case _ => None }) - def trimmedTw(): RTrivia = l.lastOption match { - case Some(_: RWhitespace) => RTrivia(l.init) + def trimmedLw(): RTrivia = l.headOption match { + case Some(_: RWhitespace) => RTrivia(l.tail) + case _ => this + } + + def replacedLw(r: RWhitespace): RTrivia = l.headOption match { + case Some(_: RWhitespace) => RTrivia(r :: l.tail) case _ => this } } @@ -108,107 +111,36 @@ object RDLineBreak extends RWhitespace { override def isNil: Boolean = false } -sealed trait ReformatPrettyPrinterBase extends PrettyPrintPrimitives { - val defaultIndent = 4 - val defaultWidth = 75 - - implicit def char(c: Char): Cont = - if (c == '\n') - line - else - text(c.toString) - - def space: Cont = - char(' ') - - def dlinebreak: Cont = - linebreak <> linebreak - - def line: Cont = line(" ") +sealed trait ReformatPrettyPrinterBase extends FastPrettyPrinterBase { + override val defaultIndent = 4 + override val defaultWidth = 75 +} - def linebreak: Cont = - line("\n") +trait ReformattableBase { + implicit class ContOps(dl: List[RNode]) { + def com(dr: List[RNode]): List[RNode] = + dl ::: dr - implicit class ContOps2(dl: List[RNode]) { def <>(dr: List[RNode]): List[RNode] = - dl ::: dr + if (dl.forall(_.isNil)) dr else if (dr.forall(_.isNil)) dl else dl com dr def <+>(dr: List[RNode]): List[RNode] = - if (dr.forall(_.isNil)) dl else if (dl.forall(_.isNil)) dr else dl ::: rs ::: dr + if (dr.forall(_.isNil)) dl else if (dl.forall(_.isNil)) dr else dl ::: rs() ::: dr def <@>(dr: List[RNode]): List[RNode] = - if (dr.forall(_.isNil)) dl else if (dl.forall(_.isNil)) dr else dl ::: rl ::: dr + if (dr.forall(_.isNil)) dl else if (dl.forall(_.isNil)) dr else dl ::: rl() ::: dr def <->(dr: List[RNode]): List[RNode] = - if (dr.forall(_.isNil)) dl else if (dl.forall(_.isNil)) dr else dl ::: rlb ::: dr - } - - implicit class ContOps(dl: Cont) { - def <>(dr: Cont): Cont = - (iw: IW) => - (c: TreeCont) => { - Call(() => - for { - t <- dr(iw)(c) - t2 <- dl(iw)(t) - } yield t2) - } - - def <+>(dr: Cont): Cont = - dl <> space <> dr - - def <@>(dr: Cont): Cont = - if (dl == nil) dr else if (dr == nil) dl else dl <> line <> dr - - def <@@>(dr: Cont): Cont = - if (dl == nil) dr else if (dr == nil) dl else dl <> linebreak <> dr - - def <@@@>(dr: Cont): Cont = - if (dl == nil) dr else if (dr == nil) dl else dl <> dr - - def <@+>(dr: Cont): Cont = - if (dl == nil) dr else if (dr == nil) dl else dl <> dr - - def <+@>(dr: Cont): Cont = - if (dl == nil) dr else if (dr == nil) dl else dl <> space <> dr + if (dr.forall(_.isNil)) dl else if (dl.forall(_.isNil)) dr else dl ::: rlb() ::: dr } } -sealed trait Separator extends ReformatPrettyPrinterBase { - def doc: Cont -} - -case class SNil() extends Separator { - override def doc: Cont = nil +trait Reformattable extends ReformattableBase with Where { + def reformat(implicit ctx: ReformatterContext): List[RNode] } -case class SSpace() extends Separator { - override def doc: Cont = space -} - -case class SLine() extends Separator { - override def doc: Cont = line -} - -case class SLinebreak() extends Separator { - override def doc: Cont = linebreak -} - -case class SDLinebreak() extends Separator { - override def doc: Cont = dlinebreak -} - - -trait Reformattable extends ReformatPrettyPrinterBase with Where { - def reformat(implicit ctx: ReformatterContext): Cont - - def reformat2(implicit ctx: ReformatterContext2): List[RNode] = throw new IllegalAccessException(s"reformat2 not implemented ${getClass}") -} - -trait ReformattableExpression extends ReformatPrettyPrinterBase { - def reformatExp(implicit ctx: ReformatterContext): Cont - - def reformatExp2(implicit ctx: ReformatterContext2): List[RNode] = throw new IllegalAccessException(s"reformatExt2 not implemented ${getClass}") +trait ReformattableExpression extends ReformattableBase { + def reformatExp(implicit ctx: ReformatterContext): List[RNode] } class ReformatterContext(val program: String, val offsets: Seq[Int]) { @@ -219,191 +151,6 @@ class ReformatterContext(val program: String, val offsets: Seq[Int]) { row + p.column - 1 } - def getTrivia(pos: (ast.Position, ast.Position), updateOffset: Boolean): Seq[Trivia] = { - (pos._1, pos._2) match { - case (p: HasLineColumn, q: HasLineColumn) => { - val p_offset = getByteOffset(p); - val q_offset = getByteOffset(q); - getTriviaByByteOffset(p_offset, if (updateOffset) Some(q_offset) else None) - } - case _ => Seq() - } - } - - def getTriviaByByteOffset(offset: Int, updateOffset: Option[Int]): Seq[Trivia] = { - if (currentOffset <= offset) { - val str = program.substring(currentOffset, offset); - currentOffset = currentOffset.max(offset); - - updateOffset match { - case Some(o) => currentOffset = o - case _ => - } - - fastparse.parse(str, programTrivia(_)) match { - case Parsed.Success(value, _) => { - value - } - case _: Parsed.Failure => Seq() - } - } else { - Seq() - }; - } -} - -object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { - override val defaultIndent = 4 - - def reformatProgram(p: PProgram): String = { - println(s"${p}"); - implicit val ctx = new ReformatterContext(p.rawProgram, p.offsets) - super.pretty(defaultWidth, show(p)) - } - - def showOption[T <: Any](n: Option[T], sep: Separator = SNil())(implicit ctx: ReformatterContext): Cont = { - n match { - case Some(r) => showAny(r, sep) - case None => nil - } - } - - def showAnnotations(annotations: Seq[PAnnotation])(implicit ctx: ReformatterContext): Cont = { - if (annotations.isEmpty) { - nil - } else { - annotations.map(show(_)).foldLeft(nil)((acc, n) => acc <@@> n) - } - } - - def showReturns(returns: Option[PMethodReturns])(implicit ctx: ReformatterContext): Cont = { - returns.map(a => nil <+> show(a)).getOrElse(nil) - } - - def showPresPosts(pres: PDelimited[_, _], posts: PDelimited[_, _])(implicit ctx: ReformatterContext): Cont = { - nest(defaultIndent, (if (pres.isEmpty) nil - else show(pres, SLinebreak())) <> - (if (posts.isEmpty) nil - else show(posts, SLinebreak()) - ) - ) - } - - def showInvs(invs: PDelimited[_, _])(implicit ctx: ReformatterContext): Cont = { - nest(defaultIndent, (if (invs.isEmpty) nil else show(invs, SLinebreak()))) - } - - def showBody(body: Reformattable, newline: Boolean)(implicit ctx: ReformatterContext): Cont = { - if (newline) { - show(body, SLinebreak()) - } else { - show(body, SSpace()) - } - } - - def show(r: Reformattable, sep: Separator = SNil())(implicit ctx: ReformatterContext): Cont = { - val updatePos = r match { - case _: PLeaf => true - case _ => false - } - - // println(s"separator: ${sep}"); - // println(s"pos: ${r.pos}"); - // println(s"node: ${r.getClass}"); - - val trivia = ctx.getTrivia(r.pos, updatePos); - - var reformatted = nil - var leadingNewlines = 0; - var leadingSpaces = 0; - var newlines = 0; - var spaces = 0; - var hasComment = false - - def getSep(newlines: Int, spaces: Int): Separator = { - if (newlines > 1) SDLinebreak() - else if (newlines > 0) SLinebreak() - else if (spaces > 0) SSpace() - else SNil() - } - - // println(trivia); - - for (t <- trivia) { - t match { - case p: PComment => { - val lw = if (!hasComment) { - leadingNewlines = newlines; - leadingSpaces = spaces; - hasComment = true; - nil - } else { - getSep(newlines, spaces).doc - } - reformatted = reformatted <> lw <> p.display - newlines = 0 - spaces = 0 - } - case _: PNewLine => newlines += 1 - case _: PSpace => spaces += 1 - case _ => - } - } - - val trailingNewlines = newlines; - val trailingSpaces = spaces; - - val formattedTrivia = if (hasComment) { - val leadingSep = getSep(leadingNewlines, leadingSpaces) - val trailingSep = getSep(trailingNewlines, trailingSpaces) - - sep match { - case _: SSpace => (if (leadingSep == SNil()) space else leadingSep.doc) <> reformatted <> - (if (trailingSep == SNil()) space else trailingSep.doc) - case _: SLinebreak => leadingSep.doc <> reformatted <> (if (trailingSep == SDLinebreak()) dlinebreak else linebreak) - case _: SLine => leadingSep.doc <> reformatted <> (if (trailingSep == SDLinebreak()) dlinebreak else line) - // `nil` and others - case _ => leadingSep.doc <> reformatted <> trailingSep.doc - } - } else { - println(s"${newlines}"); - if (newlines > 1 && sep == SLinebreak()) { - dlinebreak - } else { - sep.doc - } - } - - formattedTrivia <@@@> r.reformat(ctx) - } - - def showAny(n: Any, sep: Separator = SNil())(implicit ctx: ReformatterContext): Cont = { - n match { - case p: Reformattable => show(p, sep) - case p: Option[Any] => showOption(p, sep) - case p: Seq[Any] => showSeq(p, sep) - case p: Right[Any, Any] => showAny(p.value, sep) - case p: Left[Any, Any] => showAny(p.value, sep) - } - } - - def showSeq(l: Seq[Any], sep: Separator = SNil())(implicit ctx: ReformatterContext): Cont = { - if (l.isEmpty) { - nil - } else { - l.zipWithIndex.map(e => if (e._2 == 0) showAny(e._1, sep) else showAny(e._1, SLinebreak())).reduce(_ <> _) - } - } -} - -class ReformatterContext2(val program: String, val offsets: Seq[Int]) { - var currentOffset: Int = 0 - - def getByteOffset(p: HasLineColumn): Int = { - val row = offsets(p.line - 1); - row + p.column - 1 - } - def getTrivia(pos: (ast.Position, ast.Position), updateOffset: Boolean): RTrivia = { (pos._1, pos._2) match { case (p: HasLineColumn, q: HasLineColumn) => { @@ -431,28 +178,31 @@ class ReformatterContext2(val program: String, val offsets: Seq[Int]) { var newlines = 0 var spaces = 0 + val addTrivia = () => if (newlines > 1) { + trivia += RDLineBreak() + } else if (newlines > 0) { + trivia += RLineBreak() + } else if (spaces > 0) { + trivia += RSpace() + } + for (t <- value) { t match { case p: PComment => { - if (newlines > 1) { - trivia += RDLineBreak() - } else if (newlines > 0) { - trivia += RLineBreak() - } else if (spaces > 0) { - trivia += RSpace() - } - + addTrivia() trivia += RComment(p) newlines = 0 spaces = 0 } - case w: PNewLine => newlines += 1 - case w: PSpace => spaces += 1 + case _: PNewLine => newlines += 1 + case _: PSpace => spaces += 1 case _ => {} } } + addTrivia() + RTrivia(trivia.toList) } case _: Parsed.Failure => RTrivia(List()) @@ -463,24 +213,24 @@ class ReformatterContext2(val program: String, val offsets: Seq[Int]) { } } -class PrintContext() { +class PrintContext { var whitespace: Option[RWhitespace] = None def register(w: RWhitespace): Unit = { whitespace match { case None => whitespace = Some(w) - case Some(p: RLineBreak) => w match { - case p: RLineBreak => whitespace = Some(RDLineBreak) - case p: RDLineBreak => whitespace = Some(RDLineBreak) + case Some(_: RLineBreak) => w match { + case _: RLineBreak => whitespace = Some(RDLineBreak) + case _: RDLineBreak => whitespace = Some(RDLineBreak) } case Some(p) => whitespace = Some(p) } } } -object ReformatPrettyPrinter2 extends ReformatPrettyPrinterBase { - def reformatProgram2(p: PProgram): String = { - implicit val ctx = new ReformatterContext2(p.rawProgram, p.offsets) +object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { + def reformatProgram(p: PProgram): String = { + implicit val ctx = new ReformatterContext(p.rawProgram, p.offsets) def showWhitespace(w: Option[RWhitespace]): Cont = { w match { @@ -492,7 +242,7 @@ object ReformatPrettyPrinter2 extends ReformatPrettyPrinterBase { } } - def showTrivia(p: RTrivia, pc: PrintContext): Cont = { + def showTrivia(p: RTrivia): Cont = { if (p.l.isEmpty) { nil } else { @@ -508,21 +258,36 @@ object ReformatPrettyPrinter2 extends ReformatPrettyPrinterBase { case RNil() => nil case w: RWhitespace => { pc.register(w) - nil + showWhitespace(Some(w)) } case RText(t: String) => { - val lw = pc.whitespace pc.whitespace = None - showWhitespace(lw) <> text(t) + text(t) } case t: RTrivia => { if (t.hasComment()) { pc.whitespace match { - case None => showTrivia(t, pc) - case Some(_) => showTrivia(t.trimmedTw(), pc) + case None => showTrivia(t) + case Some(w) => w match { + case _: RLineBreak => if (t.l.headOption == Some(RDLineBreak())) { + showTrivia(t.replacedLw(RLineBreak())) + } else { + showTrivia(t.trimmedLw()) + } + case _ => showTrivia(t.trimmedLw()) + } } } else { - nil + val newlines = t.l.map(_ match { + case RLineBreak() => 1 + case RDLineBreak() => 2 + case _ => 0 + }).sum + + pc.whitespace match { + case Some(_: RLineBreak) => if (newlines > 1) linebreak else nil + case _ => nil + } } } case RGroup(l: List[RNode]) => group(showList(l, pc)) @@ -531,7 +296,6 @@ object ReformatPrettyPrinter2 extends ReformatPrettyPrinterBase { } def showList(p: List[RNode], pc: PrintContext): Cont = { - println(s"${p}") var reformatted = nil for (n <- p) { reformatted = reformatted <> showNode(n, pc) @@ -540,51 +304,53 @@ object ReformatPrettyPrinter2 extends ReformatPrettyPrinterBase { } val pc = new PrintContext() - val list = show2(p).filter(!_.isNil) + println(s"Program: ${p}") + val list = show(p).filter(!_.isNil) + println(s"IR: ${list}") super.pretty(defaultWidth, showList(list, pc)) } - def showOption2[T <: Any](n: Option[T])(implicit ctx: ReformatterContext2): List[RNode] = { + def showOption[T <: Any](n: Option[T])(implicit ctx: ReformatterContext): List[RNode] = { n match { - case Some(r) => showAny2(r) - case None => rn + case Some(r) => showAny(r) + case None => rn() } } - def showAnnotations2(annotations: Seq[PAnnotation])(implicit ctx: ReformatterContext2): List[RNode] = { + def showAnnotations(annotations: Seq[PAnnotation])(implicit ctx: ReformatterContext): List[RNode] = { if (annotations.isEmpty) { List(RNil()) } else { - annotations.map(show2(_)).reduce((acc, n) => acc ::: n) + annotations.map(show(_)).reduce((acc, n) => acc ::: n) } } - def showReturns2(returns: Option[PMethodReturns])(implicit ctx: ReformatterContext2): List[RNode] = { - returns.map(a => rs ::: show2(a)).getOrElse(rn) + def showReturns(returns: Option[PMethodReturns])(implicit ctx: ReformatterContext): List[RNode] = { + returns.map(a => rs() ::: show(a)).getOrElse(rn()) } - def showPresPosts2(pres: PDelimited[_, _], posts: PDelimited[_, _])(implicit ctx: ReformatterContext2): List[RNode] = { - rne((if (pres.isEmpty) rn - else rlb ::: show2(pres)) ::: - (if (posts.isEmpty) rn - else rlb ::: show2(posts) + def showPresPosts(pres: PDelimited[_, _], posts: PDelimited[_, _])(implicit ctx: ReformatterContext): List[RNode] = { + rne((if (pres.isEmpty) rn() + else rlb() ::: show(pres)) ::: + (if (posts.isEmpty) rn() + else rlb() ::: show(posts) ) ) } - def showInvs2(invs: PDelimited[_, _])(implicit ctx: ReformatterContext2): List[RNode] = { - rne(if (invs.isEmpty) rn else rlb ::: show2(invs)) + def showInvs(invs: PDelimited[_, _])(implicit ctx: ReformatterContext): List[RNode] = { + rne(if (invs.isEmpty) rn() else rlb() ::: show(invs)) } - def showBody2(body: Reformattable, newline: Boolean)(implicit ctx: ReformatterContext2): List[RNode] = { + def showBody(body: Reformattable, newline: Boolean)(implicit ctx: ReformatterContext): List[RNode] = { if (newline) { - rlb ::: show2(body) + rlb() ::: show(body) } else { - rs ::: show2(body) + rs() ::: show(body) } } - def show2(r: Reformattable)(implicit ctx: ReformatterContext2): List[RNode] = { + def show(r: Reformattable)(implicit ctx: ReformatterContext): List[RNode] = { val updatePos = r match { case _: PLeaf => true case _ => false @@ -592,24 +358,24 @@ object ReformatPrettyPrinter2 extends ReformatPrettyPrinterBase { val trivia = ctx.getTrivia(r.pos, updatePos); - List(trivia) ::: r.reformat2(ctx) + List(trivia) ::: r.reformat(ctx) } - def showAny2(n: Any)(implicit ctx: ReformatterContext2): List[RNode] = { + def showAny(n: Any)(implicit ctx: ReformatterContext): List[RNode] = { n match { - case p: Reformattable => show2(p) - case p: Option[Any] => showOption2(p) - case p: Seq[Any] => showSeq2(p) - case p: Right[Any, Any] => showAny2(p.value) - case p: Left[Any, Any] => showAny2(p.value) + case p: Reformattable => show(p) + case p: Option[Any] => showOption(p) + case p: Seq[Any] => showSeq(p) + case p: Right[Any, Any] => showAny(p.value) + case p: Left[Any, Any] => showAny(p.value) } } - def showSeq2(l: Seq[Any])(implicit ctx: ReformatterContext2): List[RNode] = { + def showSeq(l: Seq[Any])(implicit ctx: ReformatterContext): List[RNode] = { if (l.isEmpty) { - rn + rn() } else { - l.zipWithIndex.map(e => if (e._2 == 0) showAny2(e._1) else rlb ::: showAny2(e._1)).reduce(_ ::: _) + l.zipWithIndex.map(e => if (e._2 == 0) showAny(e._1) else rlb() ::: showAny(e._1)).reduce(_ ::: _) } } } \ No newline at end of file diff --git a/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala b/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala index 14bd9c7af..4f3f963ca 100644 --- a/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala +++ b/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala @@ -6,13 +6,14 @@ package viper.silver.plugin -import viper.silver.parser.{NameAnalyser, PAnnotationsPosition, PExp, PExtender, PKeyword, PKw, PMember, PReserved, PSpecification, PStmt, PTypeSubstitution, ReformatterContext, Translator, TypeChecker} +import viper.silver.parser.{NameAnalyser, PAnnotationsPosition, PExp, PExtender, PKeyword, PKw, PMember, PReserved, PSpecification, PStmt, PTypeSubstitution, RNode, ReformatterContext, Translator, TypeChecker} import viper.silver.ast.pretty.PrettyPrintPrimitives import viper.silver.ast.{Declaration, ErrorTrafo, Exp, ExtensionExp, ExtensionMember, ExtensionStmt, Info, Member, NoPosition, Node, Position, Stmt, Type} import viper.silver.verifier.VerificationResult import scala.collection.Set import fastparse._ +import viper.silver.parser.RText.rt trait ParserPluginTemplate { import ParserPluginTemplate.Extension @@ -94,7 +95,7 @@ trait ParserPluginTemplate { override def translateMember(t: Translator): Member = ??? override def translateMemberSignature(t: Translator): Member = super.translateMemberSignature(t) override def pretty = "" - override def reformat(implicit ctx: ReformatterContext): Cont = "" + override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt("") } case class PExampleStmt()(val pos: (Position, Position)) extends PExtender with PStmt{ @@ -103,7 +104,7 @@ trait ParserPluginTemplate { // The overridden function to translate this node to a corresponding Ast node override def translateStmt(t: Translator): Stmt = super.translateStmt(t) - override def reformat(implicit ctx: ReformatterContext): Cont = "" + override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt("") } case class PExampleExp()(val pos: (Position, Position)) extends PExtender with PExp{ @@ -115,7 +116,7 @@ trait ParserPluginTemplate { override def typecheck(t: TypeChecker, n: NameAnalyser): Option[Seq[String]] = super.typecheck(t, n) // The translator function to translate the PAst node corresponding to the Ast node override def translateExp(t: Translator): Exp = super.translateExp(t) - override def reformatExp(implicit ctx: ReformatterContext): Cont = "" + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = rt("") } /** diff --git a/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala index 33ea94178..904ce14c2 100644 --- a/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/adt/AdtPASTExtension.scala @@ -78,7 +78,7 @@ case class PAdt(annotations: Seq[PAnnotation], adt: PReserved[PAdtKeyword.type], adtType } - override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> show(adt) <+> + override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAnnotations(annotations) <-> show(adt) <+> show(idndef) <> showOption(typVars) <+> show(c) } @@ -102,7 +102,7 @@ case class PAdtSeq[T <: PNode](seq: PGrouped[PSym.Brace, Seq[T]])(val pos: (Posi def inner: Seq[T] = seq.inner override def pretty = s"${seq.l.pretty}\n ${seq.inner.map(_.pretty).mkString("\n ")}\n${seq.r.pretty}" - override def reformat(implicit ctx: ReformatterContext): Cont = { + override def reformat(implicit ctx: ReformatterContext): List[RNode] = { show(seq) } } @@ -112,7 +112,7 @@ case class PAdtFieldDecl(idndef: PIdnDef, c: PSym.Colon, typ: PType)(val pos: (P def constructor: PAdtConstructor = getAncestor[PAdtConstructor].get def annotations: Seq[PAnnotation] = Nil - override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <> + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(idndef) <> show(c) <+> show(typ) } object PAdtFieldDecl { @@ -149,7 +149,7 @@ case class PAdtConstructor(annotations: Seq[PAnnotation], idndef: PIdnDef, args: override def c = PReserved.implied(PSym.Colon) override def body = None - override def reformat(implicit ctx: ReformatterContext): Cont = showAnnotations(annotations) <@@> + override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAnnotations(annotations) <-> show(idndef) <> show(args) } @@ -180,7 +180,7 @@ case class PAdtDeriving(k: PReserved[PDerivesKeyword.type], derivingInfos: PAdtS None } - override def reformat(implicit ctx: ReformatterContext): Cont = show(k) <+> show(derivingInfos) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(k) <+> show(derivingInfos) } case class PAdtWithout(k: PReserved[PWithoutKeyword.type], blockList: PDelimited[PIdnRef[PAdtFieldDecl], PSym.Comma])(val pos: (Position, Position)) extends PExtender with PPrettySubnodes with PAdtChild { @@ -194,7 +194,7 @@ case class PAdtWithout(k: PReserved[PWithoutKeyword.type], blockList: PDelimited None } - override def reformat(implicit ctx: ReformatterContext): Cont = show(k) <+> show(blockList) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(k) <+> show(blockList) } case class PAdtDerivingInfo(idndef: PIdnDef, param: Option[PGrouped[PSym.Bracket, PType]], without: Option[PAdtWithout])(val pos: (Position, Position)) extends PExtender with PPrettySubnodes { @@ -205,7 +205,7 @@ case class PAdtDerivingInfo(idndef: PIdnDef, param: Option[PGrouped[PSym.Bracket None } - override def reformat(implicit ctx: ReformatterContext): Cont = show(idndef) <+> showOption(param) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(idndef) <+> showOption(param) } case class PAdtType(adt: PIdnRef[PAdt], args: Option[PDelimited.Comma[PSym.Bracket, PType]]) @@ -274,7 +274,7 @@ case class PAdtType(adt: PIdnRef[PAdt], args: Option[PDelimited.Comma[PSym.Brack if (s.length == 0 && args.isEmpty) this else copy(args = Some(args.get.update(s)))(pos) override def copyExtraVars(from: Any): Unit = this.kind = from.asInstanceOf[PAdtType].kind - override def reformat(implicit ctx: ReformatterContext): Cont = show(adt) <> showOption(args) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(adt) <> showOption(args) } object PAdtTypeKinds { @@ -479,7 +479,7 @@ case class PConstructorCall(idnref: PIdnRef[PAdtConstructor], callArgs: PDelimit } } - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(idnref) <> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(idnref) <> show(callArgs) <> showOption(typeAnnotated) } @@ -514,7 +514,7 @@ case class PDestructorCall(rcv: PExp, dot: PReserved[PDiscDot.type], idnref: PId } } - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(rcv) <> show(dot) <> show(idnref) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(rcv) <> show(dot) <> show(idnref) } case object PIsKeyword extends PKwOp("is") { @@ -552,5 +552,5 @@ case class PDiscriminatorCall(rcv: PExp, dot: PReserved[PDiscDot.type], is: PRes } } - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(rcv) <> show(dot) <> show(is) <> show(idnref) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(rcv) <> show(dot) <> show(is) <> show(idnref) } \ No newline at end of file diff --git a/src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePASTExtension.scala index 6176844f9..614283404 100644 --- a/src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/predicateinstance/PredicateInstancePASTExtension.scala @@ -45,6 +45,6 @@ case class PPredicateInstance(m: PReserved[PMarkerSymbol.type], idnuse: PIdnRef[ PredicateInstance(idnuse.name, args.inner.toSeq map t.exp)(t.liftPos(this)) } - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(m) <> + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(m) <> show(idnuse) <> show(args) } diff --git a/src/main/scala/viper/silver/plugin/standard/refute/RefutePASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/refute/RefutePASTExtension.scala index b7b394f00..3d6dfcfa0 100644 --- a/src/main/scala/viper/silver/plugin/standard/refute/RefutePASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/refute/RefutePASTExtension.scala @@ -23,5 +23,5 @@ case class PRefute(refute: PReserved[PRefuteKeyword.type], e: PExp)(val pos: (Po override def translateStmt(t: Translator): Stmt = Refute(t.exp(e))(t.liftPos(this)) - override def reformat(implicit ctx: ReformatterContext): Cont = show(refute) <+> show(e) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(refute) <+> show(e) } diff --git a/src/main/scala/viper/silver/plugin/standard/smoke/UnreachablePASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/smoke/UnreachablePASTExtension.scala index bf0a3b534..1548397dc 100644 --- a/src/main/scala/viper/silver/plugin/standard/smoke/UnreachablePASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/smoke/UnreachablePASTExtension.scala @@ -20,5 +20,5 @@ case class PUnreachable(kw: PReserved[PUnreachableKeyword.type])(val pos: (Posit override def translateStmt(t: Translator): Stmt = Unreachable()(t.liftPos(this)) - override def reformat(implicit ctx: ReformatterContext): Cont = show(kw) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(kw) } diff --git a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala index af53c9599..37b22965d 100644 --- a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala @@ -7,6 +7,8 @@ package viper.silver.plugin.standard.termination import viper.silver.ast._ +import viper.silver.parser.RNil.rn +import viper.silver.parser.RSpace.rs import viper.silver.parser.ReformatPrettyPrinter.{show, showOption} import viper.silver.parser.TypeHelper.Bool import viper.silver.parser._ @@ -44,8 +46,8 @@ case class PDecreasesTuple(tuple: PDelimited[PExp, PSym.Comma], condition: Optio DecreasesTuple(tuple.toSeq map t.exp, condition map (_._2) map t.exp)(t.liftPos(this)) } - override def reformatExp(implicit ctx: ReformatterContext): Cont = - show(tuple) <> condition.map((e) => space <> show(e._1) <+> show(e._2)).getOrElse(nil) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = + show(tuple) <> condition.map((e) => rs <> show(e._1) <+> show(e._2)).getOrElse(rn) } case class PDecreasesWildcard(wildcard: PReserved[PWildcardSym.type], condition: Option[(PReserved[PIfKeyword.type], PExp)] = None)(val pos: (Position, Position)) extends PDecreasesClause { @@ -60,8 +62,8 @@ case class PDecreasesWildcard(wildcard: PReserved[PWildcardSym.type], condition: DecreasesWildcard(condition map (_._2) map t.exp)(t.liftPos(this)) } - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(wildcard) <+> - condition.map((e) => show(e._1) <+> show(e._2)).getOrElse(nil) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(wildcard) <+> + condition.map((e) => show(e._1) <+> show(e._2)).getOrElse(rn) } case class PDecreasesStar(star: PSym.Star)(val pos: (Position, Position)) extends PDecreasesClause { @@ -74,6 +76,6 @@ case class PDecreasesStar(star: PSym.Star)(val pos: (Position, Position)) extend DecreasesStar()(t.liftPos(this)) } - override def reformatExp(implicit ctx: ReformatterContext): Cont = show(star) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(star) } From 761a9fefabcd4f3e39f0c82a02ff2f27ea8deb04 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Fri, 22 Nov 2024 16:35:10 +0100 Subject: [PATCH 27/47] Add short circuit --- src/main/scala/viper/silver/parser/ParseAstKeyword.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala index 7ddc23611..23daa8317 100644 --- a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala +++ b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala @@ -112,6 +112,10 @@ class PDelimited[+T, +D]( override def toString(): String = s"PDelimited($first,$inner,$end)" override def reformat(implicit ctx: ReformatterContext): List[RNode] = { + if (isEmpty) { + return rn + } + val separator = delimiters.headOption match { case Some(p: PSym.Comma) => rs case None => rn From ced300ed17b2bfeaddf6bb1c6ce6368faaf58c92 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Fri, 22 Nov 2024 16:50:02 +0100 Subject: [PATCH 28/47] Add hack for decreases keyword --- .../viper/silver/parser/ReformatPrettyPrinter.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 20cec341d..98be7aacf 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -268,14 +268,12 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { if (t.hasComment()) { pc.whitespace match { case None => showTrivia(t) - case Some(w) => w match { - case _: RLineBreak => if (t.l.headOption == Some(RDLineBreak())) { + case Some(w: RLineBreak) => if (t.l.headOption == Some(RDLineBreak())) { showTrivia(t.replacedLw(RLineBreak())) } else { - showTrivia(t.trimmedLw()) - } - case _ => showTrivia(t.trimmedLw()) + showTrivia(t.trimmedLw()) } + case Some(_) => showTrivia(t.trimmedLw()) } } else { val newlines = t.l.map(_ match { @@ -286,6 +284,8 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { pc.whitespace match { case Some(_: RLineBreak) => if (newlines > 1) linebreak else nil + // Temporary hack so that decreases keyword works + case Some(_: RSpace) => if (newlines > 1) linebreak else nil case _ => nil } } From e86b33afe0a27da2da056b4e6e055d9b62734982 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Sun, 24 Nov 2024 11:08:57 +0100 Subject: [PATCH 29/47] Only reformat on leaf nodes --- .../silver/parser/ReformatPrettyPrinter.scala | 27 +++++++++---------- .../TerminationPASTExtension.scala | 2 +- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 98be7aacf..038bb5d97 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -151,26 +151,23 @@ class ReformatterContext(val program: String, val offsets: Seq[Int]) { row + p.column - 1 } - def getTrivia(pos: (ast.Position, ast.Position), updateOffset: Boolean): RTrivia = { + def getTrivia(pos: (ast.Position, ast.Position)): RTrivia = { (pos._1, pos._2) match { case (p: HasLineColumn, q: HasLineColumn) => { val p_offset = getByteOffset(p); val q_offset = getByteOffset(q); - getTriviaByByteOffset(p_offset, if (updateOffset) Some(q_offset) else None) + getTriviaByByteOffset(p_offset, q_offset) } case _ => RTrivia(List()) } } - def getTriviaByByteOffset(offset: Int, updateOffset: Option[Int]): RTrivia = { + def getTriviaByByteOffset(offset: Int, updateOffset: Int): RTrivia = { if (currentOffset <= offset) { val str = program.substring(currentOffset, offset); currentOffset = currentOffset.max(offset); - updateOffset match { - case Some(o) => currentOffset = o - case _ => - } + currentOffset = updateOffset fastparse.parse(str, programTrivia(_)) match { case Parsed.Success(value, _) => { @@ -273,6 +270,11 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { } else { showTrivia(t.trimmedLw()) } + case Some(w: RSpace) => if (t.l.headOption == Some(RSpace())) { + showTrivia(t.trimmedLw()) + } else { + showTrivia(t) + } case Some(_) => showTrivia(t.trimmedLw()) } } else { @@ -351,14 +353,11 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { } def show(r: Reformattable)(implicit ctx: ReformatterContext): List[RNode] = { - val updatePos = r match { - case _: PLeaf => true - case _ => false + println(s"pos: ${r.pos}, node: ${r.getClass}") + r match { + case _: PLeaf => List(ctx.getTrivia(r.pos)) ::: r.reformat(ctx) + case _ => r.reformat(ctx) } - - val trivia = ctx.getTrivia(r.pos, updatePos); - - List(trivia) ::: r.reformat(ctx) } def showAny(n: Any)(implicit ctx: ReformatterContext): List[RNode] = { diff --git a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala index 37b22965d..d3c13b439 100644 --- a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala @@ -47,7 +47,7 @@ case class PDecreasesTuple(tuple: PDelimited[PExp, PSym.Comma], condition: Optio } override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = - show(tuple) <> condition.map((e) => rs <> show(e._1) <+> show(e._2)).getOrElse(rn) + (if (tuple.isEmpty) rn else show(tuple)) <> condition.map((e) => rs <> show(e._1) <+> show(e._2)).getOrElse(rn) } case class PDecreasesWildcard(wildcard: PReserved[PWildcardSym.type], condition: Option[(PReserved[PIfKeyword.type], PExp)] = None)(val pos: (Position, Position)) extends PDecreasesClause { From 3db11ed4f565bc5a67a451ce033d17151aaef836 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Sun, 24 Nov 2024 11:17:21 +0100 Subject: [PATCH 30/47] Fix trailing whitespaces --- .../viper/silver/parser/ReformatPrettyPrinter.scala | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 038bb5d97..11a00e592 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -165,8 +165,6 @@ class ReformatterContext(val program: String, val offsets: Seq[Int]) { def getTriviaByByteOffset(offset: Int, updateOffset: Int): RTrivia = { if (currentOffset <= offset) { val str = program.substring(currentOffset, offset); - currentOffset = currentOffset.max(offset); - currentOffset = updateOffset fastparse.parse(str, programTrivia(_)) match { @@ -306,10 +304,11 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { } val pc = new PrintContext() - println(s"Program: ${p}") - val list = show(p).filter(!_.isNil) - println(s"IR: ${list}") - super.pretty(defaultWidth, showList(list, pc)) + val mainProgram = show(p) + val trailing = List(ctx.getTriviaByByteOffset(ctx.program.length, ctx.program.length)) + val finalProgram = (mainProgram ::: trailing).filter(!_.isNil) + println(s"IR: ${finalProgram}") + super.pretty(defaultWidth, showList(finalProgram, pc)) } def showOption[T <: Any](n: Option[T])(implicit ctx: ReformatterContext): List[RNode] = { From 41683c176f6cba380d2656f43788af09cef1f72b Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Sun, 24 Nov 2024 13:48:05 +0100 Subject: [PATCH 31/47] Fix whitespace bug --- .../viper/silver/parser/ReformatPrettyPrinter.scala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 11a00e592..88091c00e 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -218,7 +218,7 @@ class PrintContext { case _: RLineBreak => whitespace = Some(RDLineBreak) case _: RDLineBreak => whitespace = Some(RDLineBreak) } - case Some(p) => whitespace = Some(p) + case Some(_) => whitespace = Some(w) } } } @@ -261,6 +261,7 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { } case t: RTrivia => { if (t.hasComment()) { + println(t); pc.whitespace match { case None => showTrivia(t) case Some(w: RLineBreak) => if (t.l.headOption == Some(RDLineBreak())) { @@ -284,14 +285,15 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { pc.whitespace match { case Some(_: RLineBreak) => if (newlines > 1) linebreak else nil - // Temporary hack so that decreases keyword works - case Some(_: RSpace) => if (newlines > 1) linebreak else nil case _ => nil } } } case RGroup(l: List[RNode]) => group(showList(l, pc)) - case RNest(l: List[RNode]) => nest(defaultIndent, showList(l, pc)) + case RNest(l: List[RNode]) => { + println(s"nested ${p}") + nest(defaultIndent, showList(l, pc)) + } } } From edc2e7186d886a091b07b10ea93b0262426d87bc Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Mon, 25 Nov 2024 14:32:54 +0100 Subject: [PATCH 32/47] Add a couple of tests for reformatting --- .../scala/viper/silver/parser/ReformatPrettyPrinter.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 88091c00e..0561eccfe 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -261,7 +261,7 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { } case t: RTrivia => { if (t.hasComment()) { - println(t); +// println(t); pc.whitespace match { case None => showTrivia(t) case Some(w: RLineBreak) => if (t.l.headOption == Some(RDLineBreak())) { @@ -291,7 +291,7 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { } case RGroup(l: List[RNode]) => group(showList(l, pc)) case RNest(l: List[RNode]) => { - println(s"nested ${p}") +// println(s"nested ${p}") nest(defaultIndent, showList(l, pc)) } } @@ -309,7 +309,7 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { val mainProgram = show(p) val trailing = List(ctx.getTriviaByByteOffset(ctx.program.length, ctx.program.length)) val finalProgram = (mainProgram ::: trailing).filter(!_.isNil) - println(s"IR: ${finalProgram}") +// println(s"IR: ${finalProgram}") super.pretty(defaultWidth, showList(finalProgram, pc)) } @@ -354,7 +354,7 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { } def show(r: Reformattable)(implicit ctx: ReformatterContext): List[RNode] = { - println(s"pos: ${r.pos}, node: ${r.getClass}") +// println(s"pos: ${r.pos}, node: ${r.getClass}") r match { case _: PLeaf => List(ctx.getTrivia(r.pos)) ::: r.reformat(ctx) case _ => r.reformat(ctx) From 63184b782b45e553c4a50c31b935c639ceb7275b Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 27 Nov 2024 10:22:34 +0100 Subject: [PATCH 33/47] Remove POther --- src/main/scala/viper/silver/parser/FastParser.scala | 2 +- src/main/scala/viper/silver/parser/ParseAst.scala | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/scala/viper/silver/parser/FastParser.scala b/src/main/scala/viper/silver/parser/FastParser.scala index 77dfda79c..0ae19c436 100644 --- a/src/main/scala/viper/silver/parser/FastParser.scala +++ b/src/main/scala/viper/silver/parser/FastParser.scala @@ -121,7 +121,7 @@ object FastParserCompanion { def comment[$: P]: P[PComment] = lineComment | blockComment def programTrivia[$: P]: P[Seq[Trivia]] = { - P((space | newline | comment | (AnyChar.map(_ => POther()))).repX) + P((space | newline | comment).repX) } /** * A parser which matches leading whitespaces. See `LeadingWhitespace.lw` for more info. Can only be operated on in diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 020a4b308..9a7662d83 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -2101,7 +2101,6 @@ trait PExtender extends PNode { // Trivia (comments, whitespaces) trait Trivia -case class POther() extends Trivia case class PSpace() extends Trivia case class PNewLine() extends Trivia From 22e5cdef1edb05331f54fbcb3cf3b739c1ce5392 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 27 Nov 2024 11:25:20 +0100 Subject: [PATCH 34/47] Add a test case for not working snippets --- .../viper/silver/parser/ReformatPrettyPrinter.scala | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 0561eccfe..56c9effa0 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -106,8 +106,6 @@ case class RDLineBreak() extends RWhitespace with RCommentFragment { } object RDLineBreak extends RWhitespace { - def rdlb(): List[RNode] = List(RDLineBreak()) - override def isNil: Boolean = false } @@ -261,11 +259,10 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { } case t: RTrivia => { if (t.hasComment()) { -// println(t); pc.whitespace match { case None => showTrivia(t) case Some(w: RLineBreak) => if (t.l.headOption == Some(RDLineBreak())) { - showTrivia(t.replacedLw(RLineBreak())) + showTrivia(t.replacedLw(RLineBreak())) } else { showTrivia(t.trimmedLw()) } @@ -291,7 +288,6 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { } case RGroup(l: List[RNode]) => group(showList(l, pc)) case RNest(l: List[RNode]) => { -// println(s"nested ${p}") nest(defaultIndent, showList(l, pc)) } } @@ -308,8 +304,7 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { val pc = new PrintContext() val mainProgram = show(p) val trailing = List(ctx.getTriviaByByteOffset(ctx.program.length, ctx.program.length)) - val finalProgram = (mainProgram ::: trailing).filter(!_.isNil) -// println(s"IR: ${finalProgram}") + val finalProgram = (mainProgram ::: trailing).filter(!_.isNil) super.pretty(defaultWidth, showList(finalProgram, pc)) } From 2789dc78099cbc590cb326ae6a7040bc1d6b175b Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 27 Nov 2024 11:30:55 +0100 Subject: [PATCH 35/47] Add some license headers --- .../viper/silver/frontend/ReformatterAstProvider.scala | 6 ++++++ .../scala/viper/silver/parser/ReformatPrettyPrinter.scala | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/main/scala/viper/silver/frontend/ReformatterAstProvider.scala b/src/main/scala/viper/silver/frontend/ReformatterAstProvider.scala index 75102b82d..89a22fc7c 100644 --- a/src/main/scala/viper/silver/frontend/ReformatterAstProvider.scala +++ b/src/main/scala/viper/silver/frontend/ReformatterAstProvider.scala @@ -1,3 +1,9 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// +// Copyright (c) 2011-2024 ETH Zurich. + package viper.silver.frontend import viper.silver.parser.PProgram import viper.silver.reporter.Reporter diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 56c9effa0..662bb768b 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -1,3 +1,9 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// +// Copyright (c) 2011-2024 ETH Zurich. + package viper.silver.parser import fastparse.Parsed From a252425c7c88ae854454d274674c88b2916ab5d5 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 27 Nov 2024 11:35:05 +0100 Subject: [PATCH 36/47] Revert some unnecessary changes --- .../viper/silver/ast/pretty/PrettyPrinter.scala | 17 ++--------------- .../ast/utility/rewriter/Rewritable.scala | 2 +- .../scala/viper/silver/frontend/Frontend.scala | 2 ++ 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala index 989cca495..5c13a4b92 100644 --- a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala +++ b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala @@ -346,6 +346,7 @@ trait FastPrettyPrinterBase extends PrettyPrintPrimitives { def parens (d : Cont) : Cont = char ('(') <> d <> char (')') + def brackets (d : Cont) : Cont = char ('[') <> d <> char (']') @@ -353,9 +354,7 @@ trait FastPrettyPrinterBase extends PrettyPrintPrimitives { def space : Cont = char (' ') - def dlinebreak : Cont = - linebreak <> linebreak - + def linebreak : Cont = line ("\n") @@ -376,18 +375,6 @@ trait FastPrettyPrinterBase extends PrettyPrintPrimitives { def <@> (dr: Cont) : Cont = if (dl == nil) dr else if (dr == nil) dl else dl <> line <> dr - - def <@@> (dr: Cont) : Cont = - if (dl == nil) dr else if (dr == nil) dl else dl <> linebreak <> dr - - def <@@@> (dr: Cont) : Cont = - if (dl == nil) dr else if (dr == nil) dl else dl <> dr - - def <@+> (dr: Cont) : Cont = - if (dl == nil) dr else if (dr == nil) dl else dl <> dr - - def <+@> (dr: Cont) : Cont = - if (dl == nil) dr else if (dr == nil) dl else dl <> space <> dr } def line: Cont = line(" ") diff --git a/src/main/scala/viper/silver/ast/utility/rewriter/Rewritable.scala b/src/main/scala/viper/silver/ast/utility/rewriter/Rewritable.scala index e9c9adec9..434c2ccf4 100644 --- a/src/main/scala/viper/silver/ast/utility/rewriter/Rewritable.scala +++ b/src/main/scala/viper/silver/ast/utility/rewriter/Rewritable.scala @@ -6,7 +6,7 @@ package viper.silver.ast.utility.rewriter -import viper.silver.parser.{PDomainMembers, PNode} +import viper.silver.parser.PNode import viper.silver.ast.{AtomicType, BackendFuncApp, DomainFuncApp, ErrorTrafo, FuncApp, Info, Node, Position} import scala.reflect.runtime.{universe => reflection} diff --git a/src/main/scala/viper/silver/frontend/Frontend.scala b/src/main/scala/viper/silver/frontend/Frontend.scala index 0159cc61b..eaee53fd9 100644 --- a/src/main/scala/viper/silver/frontend/Frontend.scala +++ b/src/main/scala/viper/silver/frontend/Frontend.scala @@ -7,8 +7,10 @@ package viper.silver.frontend import java.nio.file.Path + import org.slf4j.LoggerFactory import ch.qos.logback.classic.Logger + import viper.silver.ast._ import viper.silver.ast.utility.{DiskLoader, FileLoader} import viper.silver.parser.PProgram From b87849347f45fdd05ecf15d092ee1eea7bffa070 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 27 Nov 2024 11:37:42 +0100 Subject: [PATCH 37/47] Remove trailing whitespaces --- src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala index 5c13a4b92..c4b3307cc 100644 --- a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala +++ b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala @@ -354,7 +354,7 @@ trait FastPrettyPrinterBase extends PrettyPrintPrimitives { def space : Cont = char (' ') - + def linebreak : Cont = line ("\n") @@ -940,4 +940,4 @@ object FastPrettyPrinter extends FastPrettyPrinterBase with BracketPrettyPrinter group(ld <+> text(b.op) <@> rd) } -} +} \ No newline at end of file From 490ccef591c29c5e1f5505a85cf21dcaa0d9df49 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 27 Nov 2024 11:47:25 +0100 Subject: [PATCH 38/47] Remove parseResult variable --- src/main/scala/viper/silver/frontend/Frontend.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/scala/viper/silver/frontend/Frontend.scala b/src/main/scala/viper/silver/frontend/Frontend.scala index eaee53fd9..50912e219 100644 --- a/src/main/scala/viper/silver/frontend/Frontend.scala +++ b/src/main/scala/viper/silver/frontend/Frontend.scala @@ -190,9 +190,6 @@ trait DefaultFrontend extends Frontend with DefaultPhases with SingleFileFronten throw new NoSuchElementException(msg) } - // TODO: How to do this properly? - def parseResult: PProgram = pProgram.get.asInstanceOf[PProgram] - def state = _state def errors = _errors def pProgram = _parsingResult @@ -292,4 +289,4 @@ trait DefaultFrontend extends Frontend with DefaultPhases with SingleFileFronten object DefaultStates extends Enumeration { type DefaultStates = Value val Initial, Initialized, InputSet, Parsing, SemanticAnalysis, Translation, ConsistencyCheck, Verification = Value -} +} \ No newline at end of file From b38fcbc734f8a85438e686629e4274e903ec530d Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 27 Nov 2024 11:52:00 +0100 Subject: [PATCH 39/47] Whitespaces and other small changes --- .../viper/silver/frontend/ReformatterAstProvider.scala | 3 +-- src/main/scala/viper/silver/parser/FastParser.scala | 7 ++++--- .../scala/viper/silver/parser/ReformatPrettyPrinter.scala | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/scala/viper/silver/frontend/ReformatterAstProvider.scala b/src/main/scala/viper/silver/frontend/ReformatterAstProvider.scala index 89a22fc7c..be275678e 100644 --- a/src/main/scala/viper/silver/frontend/ReformatterAstProvider.scala +++ b/src/main/scala/viper/silver/frontend/ReformatterAstProvider.scala @@ -15,7 +15,6 @@ class ReformatterAstProvider(override val reporter: Reporter) extends ViperAstPr override def doParsing(input: String): Result[PProgram] = parsingInner(input, false) override def result: VerificationResult = { - if (_errors.isEmpty) { require(state >= DefaultStates.Parsing) Success @@ -24,4 +23,4 @@ class ReformatterAstProvider(override val reporter: Reporter) extends ViperAstPr Failure(_errors) } } -} +} \ No newline at end of file diff --git a/src/main/scala/viper/silver/parser/FastParser.scala b/src/main/scala/viper/silver/parser/FastParser.scala index 0ae19c436..47ac293b8 100644 --- a/src/main/scala/viper/silver/parser/FastParser.scala +++ b/src/main/scala/viper/silver/parser/FastParser.scala @@ -104,9 +104,9 @@ object FastParserCompanion { ).pos } - def space[$: P]: P[PSpace] = P(("\t" | " ") map {_ => PSpace() }) + def space[$: P]: P[PSpace] = P(("\t" | " ") map (_ => PSpace())) - def newline[$: P]: P[PNewLine] = P((StringIn("\n\r") | "\n" | "\r") map {_ => PNewLine() }) + def newline[$: P]: P[PNewLine] = P((StringIn("\n\r") | "\n" | "\r") map (_ => PNewLine())) def lineComment[$: P]: P[PComment] = { P(("//" ~~ CharsWhile(_ != '\n').?.!).map { content => @@ -120,9 +120,10 @@ object FastParserCompanion { def comment[$: P]: P[PComment] = lineComment | blockComment - def programTrivia[$: P]: P[Seq[Trivia]] = { + def trivia[$: P]: P[Seq[Trivia]] = { P((space | newline | comment).repX) } + /** * A parser which matches leading whitespaces. See `LeadingWhitespace.lw` for more info. Can only be operated on in * restricted ways (e.g. `?`, `rep`, `|` or `map`), requiring that it is eventually appended to a normal parser (of type `P[V]`). diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 662bb768b..380ffe614 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -10,7 +10,7 @@ import fastparse.Parsed import viper.silver.ast import viper.silver.ast.HasLineColumn import viper.silver.ast.pretty.FastPrettyPrinterBase -import viper.silver.parser.FastParserCompanion.programTrivia +import viper.silver.parser.FastParserCompanion.trivia import viper.silver.parser.RLine.rl import viper.silver.parser.RLineBreak.rlb import viper.silver.parser.RNest.rne @@ -171,7 +171,7 @@ class ReformatterContext(val program: String, val offsets: Seq[Int]) { val str = program.substring(currentOffset, offset); currentOffset = updateOffset - fastparse.parse(str, programTrivia(_)) match { + fastparse.parse(str, trivia(_)) match { case Parsed.Success(value, _) => { val trivia = ArrayBuffer[RCommentFragment]() var newlines = 0 From b11b00dab477fe4b06f24023e234d4b418462add Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 27 Nov 2024 12:10:51 +0100 Subject: [PATCH 40/47] Rearrange some imports --- .../viper/silver/parser/FastParser.scala | 1 + .../scala/viper/silver/parser/ParseAst.scala | 21 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/scala/viper/silver/parser/FastParser.scala b/src/main/scala/viper/silver/parser/FastParser.scala index 47ac293b8..bf4e88f66 100644 --- a/src/main/scala/viper/silver/parser/FastParser.scala +++ b/src/main/scala/viper/silver/parser/FastParser.scala @@ -1001,6 +1001,7 @@ class FastParser { } case _: Parsed.Failure => } + // There was a parsing error, parse member by member to get all errors var startIndex = 0 var members: Seq[PMember] = Nil diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 9a7662d83..85bea4595 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -6,16 +6,11 @@ package viper.silver.parser - -import viper.silver.ast -import viper.silver.ast.pretty.FastPrettyPrinterBase -import viper.silver.ast.{FilePosition, HasLineColumn, Position} -import viper.silver.parser.ReformatPrettyPrinter.{show, showAnnotations, showAny, showBody, showInvs, showOption, showPresPosts, showReturns, showSeq} - import java.util.concurrent.atomic.{AtomicInteger, AtomicLong} import viper.silver.ast.utility.Visitor import viper.silver.ast.utility.rewriter.{HasExtraValList, HasExtraVars, Rewritable, StrategyBuilder} -import viper.silver.ast.{Exp, Member, NoPosition, SourcePosition, Stmt, Type} +import viper.silver.ast.{Exp, Member, NoPosition, SourcePosition, Stmt, Type, FilePosition, HasLineColumn, Position} +import viper.silver.parser.ReformatPrettyPrinter.{show, showAnnotations, showAny, showBody, showInvs, showOption, showPresPosts, showReturns, showSeq} import viper.silver.parser.PSymOp.{EqEq, Iff, Implies} import viper.silver.parser.RGroup.rg import viper.silver.parser.RLine.rl @@ -24,7 +19,6 @@ import viper.silver.parser.RNest.rne import viper.silver.parser.RNil.rn import viper.silver.parser.RSpace.rs import viper.silver.parser.RText.rt -import viper.silver.parser.ReformatPrettyPrinter.{show, showAnnotations, showBody, showPresPosts, showReturns} import viper.silver.parser.TypeHelper._ import viper.silver.verifier.ParseReport @@ -622,7 +616,7 @@ case class PMapType(map: PKw.Map, typ: PGrouped[PSym.Bracket, PPairArgument[PTyp * a real type by macro expansion. */ case class PMacroType(use: PCall) extends PType { - override val pos: (ast.Position, ast.Position) = use.pos + override val pos: (Position, Position) = use.pos override def pretty = use.pretty override def isValidOrUndeclared: Boolean = ??? override def substitute(ts: PTypeSubstitution): PType = ??? @@ -635,7 +629,7 @@ case class PMacroType(use: PCall) extends PType { * the type of any expression whose value is meaningful in the translation. */ sealed trait PInternalType extends PType { - override val pos: (ast.Position, ast.Position) = (NoPosition, NoPosition) + override val pos: (Position, Position) = (NoPosition, NoPosition) override val subNodes: Seq[PType] = Seq() override def substitute(ts: PTypeSubstitution) = this } @@ -1872,7 +1866,12 @@ trait PNoSpecsFunction extends PAnyFunction { /////////////////////////////////////////////////////////////////////////// // Program Members -case class PProgram(imported: Seq[PProgram], members: Seq[PMember])(val pos: (Position, Position), val localErrors: Seq[ParseReport], var offsets: Seq[Int], var rawProgram: String) extends PNode { +case class PProgram(imported: Seq[PProgram], members: Seq[PMember])( + val pos: (Position, Position), + val localErrors: Seq[ParseReport], + var offsets: Seq[Int], + var rawProgram: String +) extends PNode { val imports: Seq[PImport] = members.collect { case i: PImport => i } ++ imported.flatMap(_.imports) val macros: Seq[PDefine] = members.collect { case m: PDefine => m } ++ imported.flatMap(_.macros) val domains: Seq[PDomain] = members.collect { case d: PDomain => d } ++ imported.flatMap(_.domains) From dbef7947023d4b732bf6e306a62254c78e5063d8 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 27 Nov 2024 12:17:38 +0100 Subject: [PATCH 41/47] Rename trivia to PTrivia --- .../viper/silver/parser/FastParser.scala | 2 +- .../scala/viper/silver/parser/ParseAst.scala | 22 +++++-------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/src/main/scala/viper/silver/parser/FastParser.scala b/src/main/scala/viper/silver/parser/FastParser.scala index bf4e88f66..81c47f4cb 100644 --- a/src/main/scala/viper/silver/parser/FastParser.scala +++ b/src/main/scala/viper/silver/parser/FastParser.scala @@ -120,7 +120,7 @@ object FastParserCompanion { def comment[$: P]: P[PComment] = lineComment | blockComment - def trivia[$: P]: P[Seq[Trivia]] = { + def trivia[$: P]: P[Seq[PTrivia]] = { P((space | newline | comment).repX) } diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index 85bea4595..b83392d72 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -2003,15 +2003,7 @@ case class PDomainMembers1(members: Seq[PDomainMember1])(val pos: (Position, Pos case class PFields(annotations: Seq[PAnnotation], field: PKw.Field, fields: PDelimited[PFieldDecl, PSym.Comma], s: Option[PSym.Semi])(val pos: (Position, Position)) extends PMember with PPrettySubnodes { override def declares: Seq[PGlobalDeclaration] = fields.toSeq - override def reformat(implicit ctx: ReformatterContext): List[RNode] = { - // println(s"PFields"); - // println(s"---------------------------"); - // println(s"annotation: ${annotation}"); - // println(s"field: ${field}"); - // println(s"fields: ${fields}"); - // println(s"s: ${s}"); - show(field) <+> show(fields) <> showOption(s) - } + override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(field) <+> show(fields) <> showOption(s) } case class PSpecification[+T <: PKw.Spec](k: PReserved[PKw.Spec], e: PExp)(val pos: (Position, Position)) extends PNode with PPrettySubnodes { @@ -2023,10 +2015,6 @@ case class PSpecification[+T <: PKw.Spec](k: PReserved[PKw.Spec], e: PExp)(val p case class PFunction(annotations: Seq[PAnnotation], keyword: PKw.Function, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PFormalArgDecl], c: PSym.Colon, resultType: PType, pres: PDelimited[PSpecification[PKw.PreSpec], Option[PSym.Semi]], posts: PDelimited[PSpecification[PKw.PostSpec], Option[PSym.Semi]], body: Option[PBracedExp]) (val pos: (Position, Position)) extends PSingleMember with PAnyFunction with PGlobalCallableNamedArgs with PPrettySubnodes { override def reformat(implicit ctx: ReformatterContext): List[RNode] = { - // TODO: Add PFunctioNType - println(s"PFunction"); - println(s"---------------------------"); - println(s"body ${body}"); showAnnotations(annotations) <-> show(keyword) <+> show(idndef) <> show(args) <> show(c) <+> show(resultType) <> showPresPosts(pres, posts) <> body.map(showBody(_, !(pres.isEmpty && posts.isEmpty))).getOrElse(rn) @@ -2099,11 +2087,11 @@ trait PExtender extends PNode { } // Trivia (comments, whitespaces) -trait Trivia -case class PSpace() extends Trivia -case class PNewLine() extends Trivia +trait PTrivia +case class PSpace() extends PTrivia +case class PNewLine() extends PTrivia -case class PComment(inner: String, block: Boolean) extends Trivia { +case class PComment(inner: String, block: Boolean) extends PTrivia { def str: String = if (block) { "/*" + inner + "*/" } else { From b77509ae5bd30500c2bca45ec1d9fc6c608445f8 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 27 Nov 2024 12:20:41 +0100 Subject: [PATCH 42/47] Remove LeftLineIndent --- .../viper/silver/parser/ParseAstKeyword.scala | 16 ++++++---------- .../termination/TerminationPASTExtension.scala | 5 ++--- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala index 23daa8317..781e28788 100644 --- a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala +++ b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala @@ -25,12 +25,10 @@ trait PReservedString { } trait LeftSpace extends PReservedString { override def leftPad = " " } trait RightSpace extends PReservedString { override def rightPad = " " } -trait LeftNewlineIndent extends PReservedString { override def leftPad = "\n " } case class PReserved[+T <: PReservedString](rs: T)(val pos: (Position, Position)) extends PNode with PLeaf { override def display = rs.display - def token = rs.token - override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt(token) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt(rs.token) } object PReserved { def implied[T <: PReservedString](rs: T): PReserved[T] = PReserved(rs)(NoPosition, NoPosition) @@ -172,9 +170,7 @@ sealed trait PKeywordAtom sealed trait PKeywordIf extends PKeywordStmt -abstract class PKw(val keyword: String) extends PKeyword { -// override def reformat(implicit ctx: ReformatterContext): Cont = text(keyword) -} +abstract class PKw(val keyword: String) extends PKeyword object PKw { case object Import extends PKw("import") with PKeywordLang @@ -205,11 +201,11 @@ object PKw { sealed trait Spec extends PReservedString; trait AnySpec extends PreSpec with PostSpec with InvSpec trait PreSpec extends Spec; trait PostSpec extends Spec; trait InvSpec extends Spec - case object Requires extends PKw("requires") with PKeywordLang with PreSpec with LeftNewlineIndent + case object Requires extends PKw("requires") with PKeywordLang with PreSpec type Requires = PReserved[Requires.type] - case object Ensures extends PKw("ensures") with PKeywordLang with PostSpec with LeftNewlineIndent + case object Ensures extends PKw("ensures") with PKeywordLang with PostSpec type Ensures = PReserved[Ensures.type] - case object Invariant extends PKw("invariant") with PKeywordLang with InvSpec with LeftNewlineIndent + case object Invariant extends PKw("invariant") with PKeywordLang with InvSpec type Invariant = PReserved[Invariant.type] case object Result extends PKw("result") with PKeywordLang with PKeywordAtom { @@ -564,4 +560,4 @@ object PKwOp { type Multiset = PReserved[Multiset.type] case object Map extends PKwOp("Map") with PKeywordAtom type Map = PReserved[Map.type] -} +} \ No newline at end of file diff --git a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala index d3c13b439..bc77de6ab 100644 --- a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala @@ -13,7 +13,7 @@ import viper.silver.parser.ReformatPrettyPrinter.{show, showOption} import viper.silver.parser.TypeHelper.Bool import viper.silver.parser._ -case object PDecreasesKeyword extends PKw("decreases") with PKeywordLang with PKw.AnySpec with LeftNewlineIndent +case object PDecreasesKeyword extends PKw("decreases") with PKeywordLang with PKw.AnySpec case object PIfKeyword extends PKw("if") with PKeywordLang case object PWildcardSym extends PSym("_") with PSymbolLang @@ -77,5 +77,4 @@ case class PDecreasesStar(star: PSym.Star)(val pos: (Position, Position)) extend } override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(star) -} - +} \ No newline at end of file From cbfc1058f33dcffdb795c6c806609c74c11b1b1e Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 27 Nov 2024 13:50:25 +0100 Subject: [PATCH 43/47] Readd newlines --- src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala | 2 +- src/main/scala/viper/silver/frontend/Frontend.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala index c4b3307cc..bd45fae94 100644 --- a/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala +++ b/src/main/scala/viper/silver/ast/pretty/PrettyPrinter.scala @@ -940,4 +940,4 @@ object FastPrettyPrinter extends FastPrettyPrinterBase with BracketPrettyPrinter group(ld <+> text(b.op) <@> rd) } -} \ No newline at end of file +} diff --git a/src/main/scala/viper/silver/frontend/Frontend.scala b/src/main/scala/viper/silver/frontend/Frontend.scala index 50912e219..29d83b275 100644 --- a/src/main/scala/viper/silver/frontend/Frontend.scala +++ b/src/main/scala/viper/silver/frontend/Frontend.scala @@ -289,4 +289,4 @@ trait DefaultFrontend extends Frontend with DefaultPhases with SingleFileFronten object DefaultStates extends Enumeration { type DefaultStates = Value val Initial, Initialized, InputSet, Parsing, SemanticAnalysis, Translation, ConsistencyCheck, Verification = Value -} \ No newline at end of file +} From dd071e5fdd531ccadddcde4d4a22bd3e5f0dc8bf Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Wed, 27 Nov 2024 14:25:39 +0100 Subject: [PATCH 44/47] Add some comments and improve code formatting --- .../viper/silver/parser/ParseAstKeyword.scala | 2 +- .../silver/parser/ReformatPrettyPrinter.scala | 92 ++++++++++++------- 2 files changed, 62 insertions(+), 32 deletions(-) diff --git a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala index 781e28788..09ee01e06 100644 --- a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala +++ b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala @@ -560,4 +560,4 @@ object PKwOp { type Multiset = PReserved[Multiset.type] case object Map extends PKwOp("Map") with PKeywordAtom type Map = PReserved[Map.type] -} \ No newline at end of file +} diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 380ffe614..1b173f01d 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -4,6 +4,29 @@ // // Copyright (c) 2011-2024 ETH Zurich. +/** + * The idea behind how the reformatter works is as follows: + * + * Firstly, it's based on the parse AST (PProgram) and not the Viper AST (Program), which actually already has + * a pretty printing functionality. But it's not suitable for actual reformatting for a couple of reasons: + * At the point where we generate the AST, it's already processed in a way that makes it unsuitable for formatting. + * For examples, macros will be expanded, imports will be inlined, and most importantly, information about whitespaces + * and comments is completely discarded, and so on. Because of this, using the parse AST as a basis for the formatter + * is just more sensible. + * + * The steps are as follows: + * - We first build the parse AST for a specific Viper file. + * - Then, we iterate over each node in the tree and turn it into a list of RNodes. A RNode is very similar + * to the primitives provided by `PrettyPrintPrimitives`, the reason we don't convert directly into a pretty + * print tree is that we need to perform some preprocessing on whitespaces, which is just much easier to do + * if we store everything in an intermediate representation. + * - Whenever we hit a leaf node, we get all comments and whitespaces that appear from the last position + * we stored up to that leaf node, and store them. This is necessary to preserve comments and certain kinds of + * newlines, which is important when reformatting a file. + * - Once we have our finalized list of RNodes, we convert them into a pretty print tree and print that tree, + * similarly to how it's done for the pretty printer for the Viper AST. + */ + package viper.silver.parser import fastparse.Parsed @@ -19,6 +42,7 @@ import viper.silver.parser.RSpace.rs import scala.collection.mutable.ArrayBuffer +// A reformattable node. trait RNode { def isNil: Boolean } @@ -49,11 +73,6 @@ case class RTrivia(l: List[RCommentFragment]) extends RNode { case _ => false }) - def lw(): Option[RWhitespace] = l.headOption.flatMap(_ match { - case w: RWhitespace => Some(w) - case _ => None - }) - def trimmedLw(): RTrivia = l.headOption match { case Some(_: RWhitespace) => RTrivia(l.tail) case _ => this @@ -120,7 +139,7 @@ sealed trait ReformatPrettyPrinterBase extends FastPrettyPrinterBase { override val defaultWidth = 75 } -trait ReformattableBase { +trait ReformatBase { implicit class ContOps(dl: List[RNode]) { def com(dr: List[RNode]): List[RNode] = dl ::: dr @@ -139,15 +158,17 @@ trait ReformattableBase { } } -trait Reformattable extends ReformattableBase with Where { +trait Reformattable extends ReformatBase with Where { def reformat(implicit ctx: ReformatterContext): List[RNode] } -trait ReformattableExpression extends ReformattableBase { +trait ReformattableExpression extends ReformatBase { def reformatExp(implicit ctx: ReformatterContext): List[RNode] } class ReformatterContext(val program: String, val offsets: Seq[Int]) { + // Store the last position we have processed, so we don't include certain trivia + // twice. var currentOffset: Int = 0 def getByteOffset(p: HasLineColumn): Int = { @@ -155,6 +176,10 @@ class ReformatterContext(val program: String, val offsets: Seq[Int]) { row + p.column - 1 } + // Get all trivia for a node position. The first position + // is the start position of the node (i.e. the end position when getting + // the trivia) and the second position is the end position of the node (i.e. + // the value `currentOffset` should be updated to). def getTrivia(pos: (ast.Position, ast.Position)): RTrivia = { (pos._1, pos._2) match { case (p: HasLineColumn, q: HasLineColumn) => { @@ -166,13 +191,14 @@ class ReformatterContext(val program: String, val offsets: Seq[Int]) { } } - def getTriviaByByteOffset(offset: Int, updateOffset: Int): RTrivia = { - if (currentOffset <= offset) { - val str = program.substring(currentOffset, offset); + def getTriviaByByteOffset(end: Int, updateOffset: Int): RTrivia = { + if (currentOffset <= end) { + val str = program.substring(currentOffset, end); currentOffset = updateOffset fastparse.parse(str, trivia(_)) match { case Parsed.Success(value, _) => { + // Create a list of deduplicated whitespaces, and comments. val trivia = ArrayBuffer[RCommentFragment]() var newlines = 0 var spaces = 0 @@ -196,7 +222,7 @@ class ReformatterContext(val program: String, val offsets: Seq[Int]) { } case _: PNewLine => newlines += 1 case _: PSpace => spaces += 1 - case _ => {} + case _ => } } @@ -212,12 +238,14 @@ class ReformatterContext(val program: String, val offsets: Seq[Int]) { } } -class PrintContext { +class PrettyPrintContext { var whitespace: Option[RWhitespace] = None def register(w: RWhitespace): Unit = { whitespace match { case None => whitespace = Some(w) + // If we already have a linebreak, it should not be overwritten e.g. by a space, + // and special handling applies in case we want a double line break. case Some(_: RLineBreak) => w match { case _: RLineBreak => whitespace = Some(RDLineBreak) case _: RDLineBreak => whitespace = Some(RDLineBreak) @@ -227,17 +255,16 @@ class PrintContext { } } -object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { +object ReformatPrettyPrinter extends ReformatPrettyPrinterBase with ReformatBase { def reformatProgram(p: PProgram): String = { implicit val ctx = new ReformatterContext(p.rawProgram, p.offsets) - def showWhitespace(w: Option[RWhitespace]): Cont = { + def showWhitespace(w:RWhitespace): Cont = { w match { - case None => nil - case Some(RSpace()) => space - case Some(RLine()) => line - case Some(RLineBreak()) => linebreak - case Some(RDLineBreak()) => linebreak <> linebreak + case RSpace() => space + case RLine() => line + case RLineBreak() => linebreak + case RDLineBreak() => linebreak <> linebreak } } @@ -246,18 +273,18 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { nil } else { p.l.map(t => t match { - case w: RWhitespace => showWhitespace(Some(w)) + case w: RWhitespace => showWhitespace(w) case p: RComment => text(p.comment.str) }).reduce((acc, n) => acc <> n) } } - def showNode(p: RNode, pc: PrintContext): Cont = { + def showNode(p: RNode, pc: PrettyPrintContext): Cont = { p match { case RNil() => nil case w: RWhitespace => { pc.register(w) - showWhitespace(Some(w)) + showWhitespace(w) } case RText(t: String) => { pc.whitespace = None @@ -265,13 +292,17 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { } case t: RTrivia => { if (t.hasComment()) { + // If we already had a whitespace as part of formatting the program, we might have to + // trim the leading whitespace from the trivia. pc.whitespace match { case None => showTrivia(t) + // If we want a double linebreak and we already had a linebreak, replace it with a simple linebreak. case Some(w: RLineBreak) => if (t.l.headOption == Some(RDLineBreak())) { showTrivia(t.replacedLw(RLineBreak())) } else { showTrivia(t.trimmedLw()) } + // If we want a space and already had a space, do not write double space, trim it instead. case Some(w: RSpace) => if (t.l.headOption == Some(RSpace())) { showTrivia(t.trimmedLw()) } else { @@ -293,13 +324,11 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { } } case RGroup(l: List[RNode]) => group(showList(l, pc)) - case RNest(l: List[RNode]) => { - nest(defaultIndent, showList(l, pc)) - } + case RNest(l: List[RNode]) => nest(defaultIndent, showList(l, pc)) } } - def showList(p: List[RNode], pc: PrintContext): Cont = { + def showList(p: List[RNode], pc: PrettyPrintContext): Cont = { var reformatted = nil for (n <- p) { reformatted = reformatted <> showNode(n, pc) @@ -307,8 +336,9 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { reformatted } - val pc = new PrintContext() + val pc = new PrettyPrintContext() val mainProgram = show(p) + // Don't forget the trivia after the last program node, i.e. trailing comments! val trailing = List(ctx.getTriviaByByteOffset(ctx.program.length, ctx.program.length)) val finalProgram = (mainProgram ::: trailing).filter(!_.isNil) super.pretty(defaultWidth, showList(finalProgram, pc)) @@ -355,13 +385,13 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { } def show(r: Reformattable)(implicit ctx: ReformatterContext): List[RNode] = { -// println(s"pos: ${r.pos}, node: ${r.getClass}") r match { - case _: PLeaf => List(ctx.getTrivia(r.pos)) ::: r.reformat(ctx) + case _: PLeaf => List(ctx.getTrivia(r.pos)) <> r.reformat(ctx) case _ => r.reformat(ctx) } } + // We need this method because unfortunately PGrouped and PDelimited can have arbitrary generic parameters. def showAny(n: Any)(implicit ctx: ReformatterContext): List[RNode] = { n match { case p: Reformattable => show(p) @@ -376,7 +406,7 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase { if (l.isEmpty) { rn() } else { - l.zipWithIndex.map(e => if (e._2 == 0) showAny(e._1) else rlb() ::: showAny(e._1)).reduce(_ ::: _) + l.zipWithIndex.map(e => if (e._2 == 0) showAny(e._1) else rlb() <> showAny(e._1)).reduce(_ <> _) } } } \ No newline at end of file From 04da717266c5f950a689738aa6a40503dadf5a54 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Thu, 28 Nov 2024 11:04:26 +0100 Subject: [PATCH 45/47] Add another case for showAny --- src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index 1b173f01d..f379480bb 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -399,6 +399,7 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase with ReformatBase case p: Seq[Any] => showSeq(p) case p: Right[Any, Any] => showAny(p.value) case p: Left[Any, Any] => showAny(p.value) + case p: Iterable[Any] => if (p.isEmpty) List() else p.map(showAny).reduce((a, b) => a <> b) } } From 27d001c1e0278b68efc37a5481e296435cd6a3e9 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Thu, 28 Nov 2024 11:07:19 +0100 Subject: [PATCH 46/47] Fix whitespaces and imports --- src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala | 2 +- .../plugin/standard/termination/TerminationPASTExtension.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala b/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala index 4f3f963ca..d2e29c338 100644 --- a/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala +++ b/src/main/scala/viper/silver/plugin/ParserPluginTemplate.scala @@ -7,13 +7,13 @@ package viper.silver.plugin import viper.silver.parser.{NameAnalyser, PAnnotationsPosition, PExp, PExtender, PKeyword, PKw, PMember, PReserved, PSpecification, PStmt, PTypeSubstitution, RNode, ReformatterContext, Translator, TypeChecker} +import viper.silver.parser.RText.rt import viper.silver.ast.pretty.PrettyPrintPrimitives import viper.silver.ast.{Declaration, ErrorTrafo, Exp, ExtensionExp, ExtensionMember, ExtensionStmt, Info, Member, NoPosition, Node, Position, Stmt, Type} import viper.silver.verifier.VerificationResult import scala.collection.Set import fastparse._ -import viper.silver.parser.RText.rt trait ParserPluginTemplate { import ParserPluginTemplate.Extension diff --git a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala index bc77de6ab..1749d8626 100644 --- a/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala +++ b/src/main/scala/viper/silver/plugin/standard/termination/TerminationPASTExtension.scala @@ -77,4 +77,4 @@ case class PDecreasesStar(star: PSym.Star)(val pos: (Position, Position)) extend } override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(star) -} \ No newline at end of file +} From 1784b238eb35e44318b5b2cb2ec1105610af58e9 Mon Sep 17 00:00:00 2001 From: Laurenz Stampfl Date: Thu, 28 Nov 2024 11:27:54 +0100 Subject: [PATCH 47/47] Add brackets to method calls --- .../viper/silver/frontend/Frontend.scala | 1 - .../scala/viper/silver/parser/ParseAst.scala | 46 +++++++++---------- .../viper/silver/parser/ParseAstKeyword.scala | 12 ++--- .../silver/parser/ReformatPrettyPrinter.scala | 4 +- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/main/scala/viper/silver/frontend/Frontend.scala b/src/main/scala/viper/silver/frontend/Frontend.scala index 29d83b275..bb104d4c1 100644 --- a/src/main/scala/viper/silver/frontend/Frontend.scala +++ b/src/main/scala/viper/silver/frontend/Frontend.scala @@ -13,7 +13,6 @@ import ch.qos.logback.classic.Logger import viper.silver.ast._ import viper.silver.ast.utility.{DiskLoader, FileLoader} -import viper.silver.parser.PProgram import viper.silver.reporter.StdIOReporter import viper.silver.verifier._ import viper.silver.reporter.Reporter diff --git a/src/main/scala/viper/silver/parser/ParseAst.scala b/src/main/scala/viper/silver/parser/ParseAst.scala index b83392d72..0984f79e4 100644 --- a/src/main/scala/viper/silver/parser/ParseAst.scala +++ b/src/main/scala/viper/silver/parser/ParseAst.scala @@ -1043,7 +1043,7 @@ case class PCall(idnref: PIdnRef[PCallable], callArgs: PDelimited.Comma[PSym.Par } override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(idnref) <> - show(callArgs) <> typeAnnotated.map(e => show(e._1) <+> show(e._2)).getOrElse(rn) + show(callArgs) <> typeAnnotated.map(e => show(e._1) <+> show(e._2)).getOrElse(rn()) } class PBinExp(val left: PExp, val op: PReserved[PBinaryOp], val right: PExp)(val pos: (Position, Position)) extends POpApp { @@ -1078,7 +1078,7 @@ class PBinExp(val left: PExp, val op: PReserved[PBinaryOp], val right: PExp)(val op.rs match { // Those operators look a bit better if they stick on the previous line case Iff | Implies | EqEq => - rg(show(left) <+> show(op) <> rne(rl <> show(right))) + rg(show(left) <+> show(op) <> rne(rl() <> show(right))) case _ => rg(show(left) <@> show(op) <+> show(right)) } @@ -1108,8 +1108,8 @@ case class PCondExp(cond: PExp, q: PSymOp.Question, thn: PExp, c: PSymOp.Colon, ) override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(cond) <+> show(q) <> - rne(rg(rl <> show(thn) <+> - show(c) <> rg(rl <> show(els)))) + rne(rg(rl() <> show(thn) <+> + show(c) <> rg(rl() <> show(els)))) } // Simple literals @@ -1176,7 +1176,7 @@ case class PUnfolding(unfolding: PKwOp.Unfolding, acc: PAccAssertion, in: PKwOp. override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Predicate, POpApp.pResS -> POpApp.pArg(1))) - override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(unfolding) <+> show(acc) <+> show(in) <> rne(rg(rl <> show(exp))) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(unfolding) <+> show(acc) <+> show(in) <> rne(rg(rl() <> show(exp))) } case class PApplying(applying: PKwOp.Applying, wand: PExp, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { @@ -1184,7 +1184,7 @@ case class PApplying(applying: PKwOp.Applying, wand: PExp, in: PKwOp.In, exp: PE override val signatures: List[PTypeSubstitution] = List(Map(POpApp.pArgS(0) -> Wand, POpApp.pResS -> POpApp.pArg(1))) - override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(applying) <+> show(wand) <+> show(in) <> rne(rg(rl <> show(exp))) + override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(applying) <+> show(wand) <+> show(in) <> rne(rg(rl() <> show(exp))) } case class PAsserting(asserting: PKwOp.Asserting, a: PExp, in: PKwOp.In, exp: PExp)(val pos: (Position, Position)) extends PHeapOpApp { @@ -1193,8 +1193,8 @@ case class PAsserting(asserting: PKwOp.Asserting, a: PExp, in: PKwOp.In, exp: PE List(Map(POpApp.pArgS(0) -> Impure, POpApp.pResS -> POpApp.pArg(1))) override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(asserting) <+> - rne(rg(rl <> show(a))) <+> - show(in) <> rne(rg(rl <> show(exp))) + rne(rg(rl() <> show(a))) <+> + show(in) <> rne(rg(rl() <> show(exp))) } sealed trait PBinder extends PExp with PScope { @@ -1229,12 +1229,12 @@ sealed trait PQuantifier extends PBinder { case class PExists(keyword: PKw.Exists, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier { override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <+> show(vars) <+> - show(c) <> rne(rg(rl <> (showSeq(triggers) <+> show(body)))) + show(c) <> rne(rg(rl() <> (showSeq(triggers) <+> show(body)))) } case class PForall(keyword: PKw.Forall, vars: PDelimited[PLogicalVarDecl, PSym.Comma], c: PSym.ColonColon, triggers: Seq[PTrigger], body: PExp)(val pos: (Position, Position)) extends PQuantifier { override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <+> show(vars) <+> - show(c) <> rne(rg(rl <> rg(showSeq(triggers) <+> show(body)))) + show(c) <> rne(rg(rl() <> rg(showSeq(triggers) <+> show(body)))) } case class PForPerm(keyword: PKw.Forperm, vars: PDelimited[PLogicalVarDecl, PSym.Comma], accessRes: PGrouped[PSym.Bracket, PResourceAccess], c: PSym.ColonColon, body: PExp)(val pos: (Position, Position)) extends PQuantifier { @@ -1242,7 +1242,7 @@ case class PForPerm(keyword: PKw.Forperm, vars: PDelimited[PLogicalVarDecl, PSym override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <+> show(vars) <+> show(accessRes) <+> show(c) <> - rne(rg(rl <> show(body))) + rne(rg(rl() <> show(body))) } /* Let-expressions `let x == e1 in e2` are represented by the nested structure @@ -1267,7 +1267,7 @@ case class PLet(l: PKwOp.Let, variable: PIdnDef, eq: PSymOp.EqEq, exp: PGrouped. } override def reformatExp(implicit ctx: ReformatterContext): List[RNode] = show(l) <+> show(variable) <+> - show(eq) <+> show(exp) <+> show(in) <> rg(rl <> show(nestedScope)) + show(eq) <+> show(exp) <+> show(in) <> rg(rl() <> show(nestedScope)) } case class PLetNestedScope(body: PExp)(val pos: (Position, Position)) extends PTypedVarDecl with PLocalDeclaration with PScopeUniqueDeclaration { @@ -1335,7 +1335,7 @@ case class PPairArgument[+T, +U](first: T, c: PSym.Comma, second: U)(val pos: (P override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAny(first) <> show(c) <+> showAny(second) } case class PMaybePairArgument[+T, +U](first: T, second: Option[(PSym.Comma, U)])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAny(first) <> second.map(a => show(a._1) <+> showAny(a._2)).getOrElse(rn) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAny(first) <> second.map(a => show(a._1) <+> showAny(a._2)).getOrElse(rn()) } sealed trait PAccAssertion extends PExp { @@ -1686,7 +1686,7 @@ case class PAssign(targets: PDelimited[PExp with PAssignTarget, PSym.Comma], op: sealed trait PIfContinuation extends PStmt case class PIf(keyword: PReserved[PKeywordIf], cond: PGrouped.Paren[PExp], thn: PSeqn, els: Option[PIfContinuation])(val pos: (Position, Position)) extends PStmt with PIfContinuation { override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <+> show(cond) <> - showBody(thn, false) <> els.map(showBody(_, false)).getOrElse(rn) + showBody(thn, false) <> els.map(showBody(_, false)).getOrElse(rn()) } case class PElse(k: PKw.Else, els: PSeqn)(val pos: (Position, Position)) extends PStmt with PIfContinuation { @@ -1707,7 +1707,7 @@ case class PVars(keyword: PKw.Var, vars: PDelimited[PLocalVarDecl, PSym.Comma], override def reformat(implicit ctx: ReformatterContext): List[RNode] = show(keyword) <+> show(vars) <> - init.map(s => rne(rg(rs <> show(s._1) <@> show(s._2)))).getOrElse(rn) + init.map(s => rne(rg(rs() <> show(s._1) <@> show(s._2)))).getOrElse(rn()) } case class PLabel(label: PKw.Label, idndef: PIdnDef, invs: PDelimited[PSpecification[PKw.InvSpec], Option[PSym.Semi]])(val pos: (Position, Position)) extends PStmt with PMemberDeclaration with PBackwardDeclaration { @@ -1891,9 +1891,9 @@ case class PProgram(imported: Seq[PProgram], members: Seq[PMember])( override def reformat(implicit ctx: ReformatterContext): List[RNode] = { if (members.isEmpty) - rn + rn() else - members.zipWithIndex.map(e => (if (e._2 == 0) rn else rlb) <> show(e._1)).reduce((acc, n) => acc <> n) + members.zipWithIndex.map(e => (if (e._2 == 0) rn() else rlb()) <> show(e._1)).reduce((acc, n) => acc <> n) } // Pretty print members in a specific order @@ -1937,7 +1937,7 @@ case class PDomain(annotations: Seq[PAnnotation], domain: PKw.Domain, idndef: PI override def reformat(implicit ctx: ReformatterContext): List[RNode] = { showAnnotations(annotations) <-> show(domain) <+> show(idndef) <> showOption(typVars) <> - (if (interpretations.isEmpty) rn else rne(rlb <> showOption(interpretations))) <> + (if (interpretations.isEmpty) rn() else rne(rlb() <> showOption(interpretations))) <> showBody(members, !interpretations.isEmpty) } } @@ -1994,8 +1994,8 @@ case class PAxiom1(annotations: Seq[PAnnotation], axiom: PKw.Axiom, idndef: Opti showOption(idndef) <+> show(exp) <> showOption(s) } case class PDomainMembers1(members: Seq[PDomainMember1])(val pos: (Position, Position)) extends PNode with PPrettySubnodes { - override def reformat(implicit ctx: ReformatterContext): List[RNode] = if (members.isEmpty) rn else members.zipWithIndex - .map(m => if (m._2 == 0) show(m._1) else rlb <> show(m._1)) + override def reformat(implicit ctx: ReformatterContext): List[RNode] = if (members.isEmpty) rn() else members.zipWithIndex + .map(m => if (m._2 == 0) show(m._1) else rlb() <> show(m._1)) .reduce(_ <> _) } @@ -2017,7 +2017,7 @@ case class PFunction(annotations: Seq[PAnnotation], keyword: PKw.Function, idnde override def reformat(implicit ctx: ReformatterContext): List[RNode] = { showAnnotations(annotations) <-> show(keyword) <+> show(idndef) <> show(args) <> show(c) <+> show(resultType) <> - showPresPosts(pres, posts) <> body.map(showBody(_, !(pres.isEmpty && posts.isEmpty))).getOrElse(rn) + showPresPosts(pres, posts) <> body.map(showBody(_, !(pres.isEmpty && posts.isEmpty))).getOrElse(rn()) } } @@ -2027,7 +2027,7 @@ case class PPredicate(annotations: Seq[PAnnotation], keyword: PKw.Predicate, idn override def resultType = Predicate override def reformat(implicit ctx: ReformatterContext): List[RNode] = showAnnotations(annotations) <-> show(keyword) <+> show(idndef) <> - show(args) <> body.map(showBody(_, false)).getOrElse(rn) + show(args) <> body.map(showBody(_, false)).getOrElse(rn()) } case class PMethod(annotations: Seq[PAnnotation], keyword: PKw.Method, idndef: PIdnDef, args: PDelimited.Comma[PSym.Paren, PFormalArgDecl], returns: Option[PMethodReturns], pres: PDelimited[PSpecification[PKw.PreSpec], Option[PSym.Semi]], posts: PDelimited[PSpecification[PKw.PostSpec], Option[PSym.Semi]], body: Option[PSeqn]) @@ -2037,7 +2037,7 @@ case class PMethod(annotations: Seq[PAnnotation], keyword: PKw.Method, idndef: P override def reformat(implicit ctx: ReformatterContext): List[RNode] = { showAnnotations(annotations) <-> show(keyword) <+> show(idndef) <> show(args) <> showReturns(returns) <> - showPresPosts(pres, posts) <> body.map(showBody(_, !(returns.isEmpty && pres.isEmpty && posts.isEmpty))).getOrElse(rn) + showPresPosts(pres, posts) <> body.map(showBody(_, !(returns.isEmpty && pres.isEmpty && posts.isEmpty))).getOrElse(rn()) } } diff --git a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala index 09ee01e06..ebbfe1b73 100644 --- a/src/main/scala/viper/silver/parser/ParseAstKeyword.scala +++ b/src/main/scala/viper/silver/parser/ParseAstKeyword.scala @@ -50,7 +50,7 @@ case class PGrouped[G <: PSym.Group, +T](l: PReserved[G#L], inner: T, r: PReserv if (inner_.forall(_.isNil)) { left <> right } else { - left <> rne(rl <> inner_) <> rl <> right + left <> rne(rl() <> inner_) <> rl() <> right } } else { show(l) <> rne(showAny(inner)) <> show(r) @@ -111,17 +111,17 @@ class PDelimited[+T, +D]( override def reformat(implicit ctx: ReformatterContext): List[RNode] = { if (isEmpty) { - return rn + return rn() } val separator = delimiters.headOption match { - case Some(p: PSym.Comma) => rs - case None => rn - case _ => rlb + case Some(p: PSym.Comma) => rs() + case None => rn() + case _ => rlb() }; showAny(first) <> - inner.foldLeft(rn)((acc, b) => acc <> showAny(b._1) <> separator <> showAny(b._2)) <> + inner.foldLeft(rn())((acc, b) => acc <> showAny(b._1) <> separator <> showAny(b._2)) <> showAny(end) } } diff --git a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala index f379480bb..490392886 100644 --- a/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala +++ b/src/main/scala/viper/silver/parser/ReformatPrettyPrinter.scala @@ -297,13 +297,13 @@ object ReformatPrettyPrinter extends ReformatPrettyPrinterBase with ReformatBase pc.whitespace match { case None => showTrivia(t) // If we want a double linebreak and we already had a linebreak, replace it with a simple linebreak. - case Some(w: RLineBreak) => if (t.l.headOption == Some(RDLineBreak())) { + case Some(_: RLineBreak) => if (t.l.headOption == Some(RDLineBreak())) { showTrivia(t.replacedLw(RLineBreak())) } else { showTrivia(t.trimmedLw()) } // If we want a space and already had a space, do not write double space, trim it instead. - case Some(w: RSpace) => if (t.l.headOption == Some(RSpace())) { + case Some(_: RSpace) => if (t.l.headOption == Some(RSpace())) { showTrivia(t.trimmedLw()) } else { showTrivia(t)