From 84b0322b94e3ca18cea15e7a93a76aa726331551 Mon Sep 17 00:00:00 2001 From: Kevin Thompson Date: Tue, 8 Sep 2026 22:08:02 -0700 Subject: [PATCH 1/2] fix(lint): reformat sources with scalafmt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI's scalafmtCheckAll was failing across metadata, pncs, runtime, and test — many files had drifted out of sync with .scalafmt.conf. Ran scalafmtAll; no logic changes. Co-Authored-By: Claude Sonnet 5 --- metadata/src/main/scala/Builtin.scala | 42 +-- metadata/src/main/scala/Metadata.scala | 4 +- metadata/src/main/scala/Opcode.scala | 6 +- pncs/src/main/scala/Ast.scala | 28 +- pncs/src/main/scala/AstPrinter.scala | 5 +- pncs/src/main/scala/BinaryOperators.scala | 7 +- pncs/src/main/scala/Binder.scala | 284 ++++++++++-------- .../src/main/scala/BoundAssemblyPrinter.scala | 31 +- pncs/src/main/scala/BoundNodes.scala | 14 +- pncs/src/main/scala/CompilerSettings.scala | 4 +- pncs/src/main/scala/DiagnosticBag.scala | 18 +- pncs/src/main/scala/Emitter.scala | 52 ++-- pncs/src/main/scala/ExprBinder.scala | 16 +- pncs/src/main/scala/Lowered.scala | 31 +- .../main/scala/LoweredAssemblyPrinter.scala | 4 +- pncs/src/main/scala/Parser.scala | 24 +- pncs/src/main/scala/Program.scala | 5 +- pncs/src/main/scala/SymbolKind.scala | 6 +- pncs/src/main/scala/SyntaxFacts.scala | 10 +- pncs/src/main/scala/TypeInference.scala | 3 +- pncs/src/main/scala/VM.scala | 124 ++++---- pncs/src/main/scala/compilation.scala | 6 +- runtime/src/main/scala/Dictionary.scala | 2 +- test/src/test/scala/BinderTests.scala | 62 ++-- test/src/test/scala/CalliTests.scala | 7 +- test/src/test/scala/ParserTests.scala | 3 +- test/src/test/scala/PnbTests.scala | 12 +- test/src/test/scala/SampleTests.scala | 24 +- test/src/test/scala/TestHelpers.scala | 10 +- test/src/test/scala/TranspilerTests.scala | 16 +- test/src/test/scala/TypeTests.scala | 6 +- test/src/test/scala/VmTests.scala | 197 ++++++++---- 32 files changed, 612 insertions(+), 451 deletions(-) diff --git a/metadata/src/main/scala/Builtin.scala b/metadata/src/main/scala/Builtin.scala index f38cd7d..7f93b62 100644 --- a/metadata/src/main/scala/Builtin.scala +++ b/metadata/src/main/scala/Builtin.scala @@ -66,27 +66,27 @@ object Builtin { /** The id for a method's qualified name, or `None` if it names no builtin. */ def idOf(qualifiedName: string): int = { qualifiedName match { - case "println" => Println - case "print" => Print - case "panic" => Panic - case "exit" => Exit - case "assert" => Assert - case "mod" => Mod - case "string.apply" => StringApply - case "int.apply" => IntApply - case "bool.apply" => BoolApply - case "char.apply" => CharApply - case "string.substring" => Substring - case "string.endsWith" => EndsWith - case "string.compareTo" => StringCompareTo - case "int.compareTo" => IntCompareTo - case "File.readAllText" => ReadAllText - case "File.readAllBytes" => ReadAllBytes - case "File.writeAllBytes" => WriteAllBytes - case "File.writeAllText" => WriteAllText - case "Path.combine" => PathCombine - case "Path.nameWithoutExtension" => PathName - case _ => None + case "println" => Println + case "print" => Print + case "panic" => Panic + case "exit" => Exit + case "assert" => Assert + case "mod" => Mod + case "string.apply" => StringApply + case "int.apply" => IntApply + case "bool.apply" => BoolApply + case "char.apply" => CharApply + case "string.substring" => Substring + case "string.endsWith" => EndsWith + case "string.compareTo" => StringCompareTo + case "int.compareTo" => IntCompareTo + case "File.readAllText" => ReadAllText + case "File.readAllBytes" => ReadAllBytes + case "File.writeAllBytes" => WriteAllBytes + case "File.writeAllText" => WriteAllText + case "Path.combine" => PathCombine + case "Path.nameWithoutExtension" => PathName + case _ => None } } diff --git a/metadata/src/main/scala/Metadata.scala b/metadata/src/main/scala/Metadata.scala index ae83486..1ffdc4d 100644 --- a/metadata/src/main/scala/Metadata.scala +++ b/metadata/src/main/scala/Metadata.scala @@ -268,8 +268,8 @@ case class Metadata() { /** Every table, in an order `read` repeats. * * Strings were left out, which is why nothing could be read back: every - * other table refers to one by token, so an image without them has names - * for nothing and `Ldstr` has no literal to load. + * other table refers to one by token, so an image without them has names for + * nothing and `Ldstr` has no literal to load. */ def write(buffer: IntList): unit = { typeDefs.write(buffer) diff --git a/metadata/src/main/scala/Opcode.scala b/metadata/src/main/scala/Opcode.scala index 0b8c16d..424121b 100644 --- a/metadata/src/main/scala/Opcode.scala +++ b/metadata/src/main/scala/Opcode.scala @@ -63,9 +63,9 @@ object Opcode { /** Call a builtin, whose id is the operand. * - * A builtin is an `extern` method with no body to call into. One - * instruction rather than one per builtin: the id says which, so declaring - * a builtin does not grow the instruction set. See `Builtin`. + * A builtin is an `extern` method with no body to call into. One instruction + * rather than one per builtin: the id says which, so declaring a builtin + * does not grow the instruction set. See `Builtin`. */ val Callx = 62 diff --git a/pncs/src/main/scala/Ast.scala b/pncs/src/main/scala/Ast.scala index cedbe2c..e7c4433 100644 --- a/pncs/src/main/scala/Ast.scala +++ b/pncs/src/main/scala/Ast.scala @@ -252,8 +252,8 @@ case class GenericParametersSyntax( case class SeparatedSyntaxList[T](items: List[T], separators: List[SyntaxToken]) -/** One trait named inside a `derive` attribute, with the comma that follows - * it, if any — the same shape `ParameterSyntax` uses for its list. +/** One trait named inside a `derive` attribute, with the comma that follows it, + * if any — the same shape `ParameterSyntax` uses for its list. */ case class DerivedTraitSyntax( name: SyntaxToken, @@ -262,9 +262,9 @@ case class DerivedTraitSyntax( /** `[derive(Eq, Ord, Show)]` ahead of a class or enum. * - * Derivation is opt-in: a type with no attribute gets no evidence, so `a == - * b` on it is a diagnostic rather than a silent identity comparison - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * Derivation is opt-in: a type with no attribute gets no evidence, so `a == b` + * on it is a diagnostic rather than a silent identity comparison ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ case class DeriveAttributeSyntax( openBracketToken: SyntaxToken, @@ -302,10 +302,12 @@ enum MemberSyntax { typeAnnotation: Option[TypeAnnotationSyntax], body: Option[FunctionBodySyntax] ) + /** A trait declares a capability: a name, its type parameters, and the * members an instance has to supply. It has no constructor parameters * because a trait is never instantiated — evidence for it comes from a - * `given` ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * `given` ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ case TraitDeclarationSyntax( traitKeyword: SyntaxToken, @@ -313,13 +315,15 @@ enum MemberSyntax { genericParameters: Option[GenericParametersSyntax], template: TemplateSyntax ) + /** `given Eq[int] { … }`, or with a premise, * `given [T: Ord] => Ord[List[T]] { … }`. * * The type parameters and the `=>` travel together: a given with nothing to * bind has neither. There is no name — under global coherence there is one * given per `(trait, type)` pair, so a name would have nothing to select - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ case GivenDeclarationSyntax( givenKeyword: SyntaxToken, @@ -542,13 +546,13 @@ object AstUtils { locationOfBoundExpression(left).merge(locationOfBoundExpression(right)) case BoundExpression.Block(statements, expression) => locationOfBoundExpression(expression) - case BoundExpression.Boolean(location, _) => location - case BoundExpression.Call(location, _, _, _, _, _) => location + case BoundExpression.Boolean(location, _) => location + case BoundExpression.Call(location, _, _, _, _, _) => location case BoundExpression.EvidenceCall(location, _, _, _, _) => location case BoundExpression.EvidenceRecord(location, _, _) => location - case BoundExpression.Cast(location, expression, _) => location - case BoundExpression.Character(location, _) => location - case BoundExpression.For(location, _, _, _, _) => location + case BoundExpression.Cast(location, expression, _) => location + case BoundExpression.Character(location, _) => location + case BoundExpression.For(location, _, _, _, _) => location case BoundExpression.If( location, cond, diff --git a/pncs/src/main/scala/AstPrinter.scala b/pncs/src/main/scala/AstPrinter.scala index a717328..d019da4 100644 --- a/pncs/src/main/scala/AstPrinter.scala +++ b/pncs/src/main/scala/AstPrinter.scala @@ -137,8 +137,9 @@ class AstPrinter(withColor: bool, buffer: IndentedStringBuilder) { case Option.Some(value) => printGenericParameters(value) } node.arrowToken match { - case Option.None => () - case Option.Some(value) => printTokenWithColor(value, ColorPalette.Keyword) + case Option.None => () + case Option.Some(value) => + printTokenWithColor(value, ColorPalette.Keyword) } printName(node.name) printTemplate(node.template) diff --git a/pncs/src/main/scala/BinaryOperators.scala b/pncs/src/main/scala/BinaryOperators.scala index 7e90f97..5d5e6eb 100644 --- a/pncs/src/main/scala/BinaryOperators.scala +++ b/pncs/src/main/scala/BinaryOperators.scala @@ -115,8 +115,8 @@ case class BinaryOperators(binder: Binder) { * question the caller asks last, because evidence has to come first: a type * with `Eq` evidence must compare through that evidence rather than by * identity, and folding the identity rule in here would answer before the - * evidence was ever consulted - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * evidence was ever consulted ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def checkBinary( left: Type, @@ -124,7 +124,8 @@ case class BinaryOperators(binder: Binder) { operator: BinaryOperatorKind ): Type = _checkBinary(binaryOps, left, right, operator) - /** [ADR 0003](../../../docs/architecture/adr/0003-equality-on-reference-types.md)'s + /** [ADR + * 0003](../../../docs/architecture/adr/0003-equality-on-reference-types.md)'s * rule, now the last resort rather than part of the table lookup. */ def referenceEquality( diff --git a/pncs/src/main/scala/Binder.scala b/pncs/src/main/scala/Binder.scala index 390306d..6c414fe 100644 --- a/pncs/src/main/scala/Binder.scala +++ b/pncs/src/main/scala/Binder.scala @@ -44,12 +44,12 @@ enum FieldOptions { /** A resolved proof, and the static field its record lives in. * * One per ground goal rather than one per given, because a conditional given - * proves a different thing at every instantiation - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision B). `premises` are the given's constraints with this - * instantiation's type arguments substituted in, so they are ground goals too - * and name the records the dependency half points at — `Eq[List[Symbol]]` - * holding a reference to `Eq[Symbol]`, which is ADR 0005's recursive evidence. + * proves a different thing at every instantiation ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * B). `premises` are the given's constraints with this instantiation's type + * arguments substituted in, so they are ground goals too and name the records + * the dependency half points at — `Eq[List[Symbol]]` holding a reference to + * `Eq[Symbol]`, which is ADR 0005's recursive evidence. */ case class BoundEvidenceRecord( goal: Type, @@ -69,11 +69,11 @@ case class BoundEvidenceRecord( /** A given's member, resolved for a particular goal. * * `record` is what proves that goal, which the caller passes as the member's - * trailing argument - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). `typeArguments` are what instantiated the given: a conditional - * given's member is declared in that given's own type variables, so a caller - * has to substitute before it can check operands against the signature. + * trailing argument ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). `typeArguments` are what instantiated the given: a conditional given's + * member is declared in that given's own type variables, so a caller has to + * substitute before it can check operands against the signature. */ case class GivenMember( member: Symbol, @@ -102,8 +102,8 @@ case class BoundGiven( * A derived body over `items: List[T]` needs `Eq[List[$0]]`, which is * neither ground — so no static record proves it — nor one of the declared * premises. It becomes a dependency of this given instead, resolved per - * instantiation exactly as a premise is - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md)). + * instantiation exactly as a premise is ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md)). * * Growable, and read rather than snapshotted everywhere, because a body is * built after the records that will hold its slots have been interned. @@ -116,8 +116,8 @@ case class BoundGiven( * The two halves happen in different passes because they need different * things: registering needs only the type, so that coherence sees the given * and evidence records can be laid out, while a body reads the constructor - * parameters' field types, which are not bound until later - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * parameters' field types, which are not bound until later ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ case class Derivation( typeSymbol: Symbol, @@ -132,10 +132,9 @@ case class Derivation( /** One case of an enum being derived for, in declaration order. * * A class's derivation has no cases and reads `parameterNames`; an enum's has - * a case per alternative and no parameters of its own. The order is the - * enum's own, which is what `Ord` compares by before it looks at any - * parameter - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * a case per alternative and no parameters of its own. The order is the enum's + * own, which is what `Ord` compares by before it looks at any parameter ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ case class DerivedCase( symbol: Symbol, @@ -469,9 +468,10 @@ case class Binder( /** `system.io`, which the Scala side shims in * [`panther.scala`](../../../../runtime/src/main/scala/panther.scala) — the - * one file `sbt pncs/transpile` skips ([`build.sbt:43`](../../../../build.sbt:43)), - * so there is no generated `.pn` for these to bind to and they have to be - * declared here like the rest of the prelude. + * one file `sbt pncs/transpile` skips + * ([`build.sbt:43`](../../../../build.sbt:43)), so there is no generated + * `.pn` for these to bind to and they have to be declared here like the rest + * of the prelude. * * At the root rather than under a `system.io` namespace, because the binder * does not bind `using` directives at all: they are parsed, printed and @@ -511,7 +511,13 @@ case class Binder( ListModule.one( Tuple2( "bytes", - Type.Class(noLoc, List.Nil, "Array", ListModule.one(intType), arraySymbol) + Type.Class( + noLoc, + List.Nil, + "Array", + ListModule.one(intType), + arraySymbol + ) ) ) ), @@ -604,7 +610,8 @@ case class Binder( * * A token may be claimed by at most one trait, so that `a == b` resolves to * one piece of evidence rather than needing overload resolution across - * traits ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * traits ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). * * Keyed by token kind rather than by text: a kind has exactly one spelling, * while `SyntaxFacts.getBinaryOperatorText` gives `&&` for both `LogicalAnd` @@ -615,10 +622,10 @@ case class Binder( /** Every evidence record the program needs, in reverse discovery order. * * Interned as resolution reaches each ground goal, rather than laid out once - * per given: a conditional given has no single record to lay out - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision B). Discovery order is a function of the source, which is what - * stage 3 needs — the field order is part of the bytecode. + * per given: a conditional given has no single record to lay out ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * B). Discovery order is a function of the source, which is what stage 3 + * needs — the field order is part of the bytecode. * * Each holds a static field on the program object; the emitter fills the * slots, being the first place method tokens are known. @@ -660,10 +667,10 @@ case class Binder( /** The record's element type is `any` rather than `int` because the slots * hold two kinds of thing: a method token in the token half, and a reference - * to another record in the dependency half - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision A). The VM's array is untyped — the element type only picks a - * default value — so this costs nothing at runtime. + * to another record in the dependency half ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * A). The VM's array is untyped — the element type only picks a default + * value — so this costs nothing at runtime. */ val evidenceRecordType: Type = Type.Class( @@ -780,16 +787,20 @@ case class Binder( val value = param(symbol, "value", operand) setSymbolType( symbol, - Type.Function(noLoc, ListModule.one(BoundParameter(value, operand)), result) + Type.Function( + noLoc, + ListModule.one(BoundParameter(value, operand)), + result + ) ) defineSelfEvidence(symbol) symbol } /** Every member of a given takes the record it was reached through, whether - * or not that given has premises - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). + * or not that given has premises ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). * * Uniform because `Calli` is: the VM reads the argument count from the * *callee's* metadata, and a caller dispatching on a token it read out of a @@ -801,8 +812,8 @@ case class Binder( * in `Type.Function.parameters` both leave it out — the arity a diagnostic * reports is still the one the source wrote (ADR 0005, decision E). * - * A trait's own members go through the same two builders and are not - * given members, which is what the owner check is for. + * A trait's own members go through the same two builders and are not given + * members, which is what the owner check is for. */ def defineSelfEvidence(member: Symbol): unit = { member.parent match { @@ -810,7 +821,7 @@ case class Binder( case Option.Some(owner) => if (owner.kind == SymbolKind.Given) { member.tryDefineEvidence(selfEvidenceName, member.location) match { - case Either.Left(_) => () + case Either.Left(_) => () case Either.Right(symbol) => // Typed as what the given proves, not as the record's own // `Array[any]`. The value is the same either way — the emitter @@ -839,8 +850,8 @@ case class Binder( /** Registers a prelude given and returns its symbol. * * Named after what it proves rather than numbered. `bindGiven` numbers the - * givens it binds so that the numbering is deterministic across compilers; - * a prelude given is already deterministic, and a name keeps the user's + * givens it binds so that the numbering is deterministic across compilers; a + * prelude given is already deterministic, and a name keeps the user's * `$given$0` the first one they wrote. */ def builtinGiven(traitSymbol: Symbol, typ: Type, typeName: string): Symbol = { @@ -865,9 +876,9 @@ case class Binder( /** A prelude given's member, whose body is the operator the builtin table * already has a row for: `Eq[int].==` is `a == b` on two ints. * - * The body is a bound expression rather than parsed source, so it skips - * type checking — which is the point, since the check it would go through - * is the one that sends `a == b` back here looking for evidence. + * The body is a bound expression rather than parsed source, so it skips type + * checking — which is the point, since the check it would go through is the + * one that sends `a == b` back here looking for evidence. */ def builtinBinaryBody( owner: Symbol, @@ -983,7 +994,11 @@ case class Binder( ) ) - def declareLocal(symbol: Symbol, typ: Type, init: BoundExpression): BoundStatement = + def declareLocal( + symbol: Symbol, + typ: Type, + init: BoundExpression + ): BoundStatement = BoundStatement.VariableDeclaration(symbol, false, typ, init) def arrayLengthOf(array: Symbol): BoundExpression = @@ -1245,7 +1260,13 @@ case class Binder( BinaryOperatorKind.LessThanOrEqual, boolType ) - builtinBinaryBody(symbol, ">", typ, BinaryOperatorKind.GreaterThan, boolType) + builtinBinaryBody( + symbol, + ">", + typ, + BinaryOperatorKind.GreaterThan, + boolType + ) builtinBinaryBody( symbol, ">=", @@ -1316,7 +1337,7 @@ case class Binder( parameters: List[Tuple2[string, Type]] ): List[BoundParameter] = parameters match { - case List.Nil => List.Nil + case List.Nil => List.Nil case List.Cons(Tuple2(name, typ), rest) => // The head is defined before the tail is walked, so the parameters end // up in the order they were written. @@ -1800,19 +1821,19 @@ case class Binder( case _: BoundExpression.Unit => unitType case _: BoundExpression.While => unitType - case expr: BoundExpression.ArrayCreation => expr.resultType + case expr: BoundExpression.ArrayCreation => expr.resultType case expr: BoundExpression.EvidenceCall => expr.resultType case expr: BoundExpression.EvidenceRecord => expr.resultType - case expr: BoundExpression.Binary => expr.resultType - case expr: BoundExpression.Block => getType(expr.expression) - case expr: BoundExpression.Call => expr.resultType - case expr: BoundExpression.Cast => expr.targetType - case expr: BoundExpression.Index => expr.resultType - case expr: BoundExpression.If => expr.resultType - case expr: BoundExpression.Match => expr.resultType - case expr: BoundExpression.MemberAccess => expr.resultType - case expr: BoundExpression.New => expr.resultType - case expr: BoundExpression.Unary => expr.resultType + case expr: BoundExpression.Binary => expr.resultType + case expr: BoundExpression.Block => getType(expr.expression) + case expr: BoundExpression.Call => expr.resultType + case expr: BoundExpression.Cast => expr.targetType + case expr: BoundExpression.Index => expr.resultType + case expr: BoundExpression.If => expr.resultType + case expr: BoundExpression.Match => expr.resultType + case expr: BoundExpression.MemberAccess => expr.resultType + case expr: BoundExpression.New => expr.resultType + case expr: BoundExpression.Unary => expr.resultType case expr: BoundExpression.Variable => expr.resultType match { case Option.None => getSymbolType(expr.symbol) @@ -2876,9 +2897,9 @@ case class Binder( } } - /** Only the prelude's three traits can be derived: derivation is a rule - * about what each of them means over a list of parameters, and there is no - * such rule for a trait the compiler has never seen. + /** Only the prelude's three traits can be derived: derivation is a rule about + * what each of them means over a list of parameters, and there is no such + * rule for a trait the compiler has never seen. */ def derivableTrait(name: string): Option[Symbol] = { if (name == "Eq") Option.Some(eqSymbol) @@ -3202,10 +3223,10 @@ case class Binder( * for `leftType`. * * The premise is not a symbol — it is a slot in the dependency half of the - * record the member was reached through - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision D), which is what `scanEvidenceMembers` cannot find by walking - * members. Inside `given [T: Ord] => Ord[Box[T]]`, `a.value.compare(b.value)` + * record the member was reached through ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * D), which is what `scanEvidenceMembers` cannot find by walking members. + * Inside `given [T: Ord] => Ord[Box[T]]`, `a.value.compare(b.value)` * resolves `compare` here. * * Only a method directly inside a given has one, which is what the @@ -3302,7 +3323,7 @@ case class Binder( */ def evidenceGoal(evidence: BoundEvidence): Type = { evidence match { - case BoundEvidence.Held(symbol) => getSymbolType(symbol) + case BoundEvidence.Held(symbol) => getSymbolType(symbol) case BoundEvidence.Premise(_, _, goal) => goal } } @@ -3313,7 +3334,7 @@ case class Binder( members: List[Symbol] ): Option[KeyValue[BoundEvidence, Symbol]] = { members match { - case List.Nil => Option.None + case List.Nil => Option.None case List.Cons(head, tail) => // Evidence reaches a body two ways: as its own parameter, or as the // field a constrained class stores its constructor's evidence in. The @@ -3324,9 +3345,8 @@ case class Binder( // annotated: the self-hosted compiler does not widen the branches of // an `if` to their common supertype val found: Option[KeyValue[BoundEvidence, Symbol]] = - if ( - head.kind != SymbolKind.Evidence && head.kind != SymbolKind.Field - ) Option.None + if (head.kind != SymbolKind.Evidence && head.kind != SymbolKind.Field) + Option.None else tryGetSymbolType(head) match { case Option.Some( @@ -3359,8 +3379,8 @@ case class Binder( * last and both `getMethodParameterMap` and metadata emission give them the * trailing argument slots. Appending rather than prepending is what keeps * every declared parameter at the slot it already had — the VM reserves slot - * 0 for the receiver and numbers declared parameters from 1 - * ([ADR 0005](../../../docs/architecture/adr/0005-evidence-representation.md), + * 0 for the receiver and numbers declared parameters from 1 ([ADR + * 0005](../../../docs/architecture/adr/0005-evidence-representation.md), * decision A). * * Order is type-parameter declaration order, which `bindGenericConstraints` @@ -3374,7 +3394,7 @@ case class Binder( scope: Scope ): List[Symbol] = { constraints match { - case List.Nil => List.Nil + case List.Nil => List.Nil case List.Cons(constraint, tail) => // define before recursing: `symbol.members()` is in definition order, // and that order is the argument slot order @@ -3517,7 +3537,11 @@ case class Binder( case List.Nil => acc case List.Cons(head, tail) => val separator = if (acc == "") "" else ", " - renderGoalList(tail, generics, acc + separator + renderGoal(head, generics)) + renderGoalList( + tail, + generics, + acc + separator + renderGoal(head, generics) + ) } } @@ -3596,11 +3620,11 @@ case class Binder( def isGroundType(typ: Type): bool = { typ match { - case Type.Variable(_, _) => false - case Type.Class(_, _, _, args, _) => isGroundTypeList(args) + case Type.Variable(_, _) => false + case Type.Class(_, _, _, args, _) => isGroundTypeList(args) case Type.Alias(_, _, _, args, _, _) => isGroundTypeList(args) - case Type.Union(_, cases) => isGroundTypeList(cases) - case _ => true + case Type.Union(_, cases) => isGroundTypeList(cases) + case _ => true } } @@ -3623,9 +3647,9 @@ case class Binder( * needs `Eq[List[Symbol]]`, which needs `Eq[Symbol]` again and finds the * record already being built. ADR 0005 asks for exactly that rule, and it * costs nothing here because a record is an array — a reference to one that - * is allocated but not yet filled is still a usable reference - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision E). + * is allocated but not yet filled is still a usable reference ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * E). */ def resolveEvidence( rawGoal: Type, @@ -3782,9 +3806,9 @@ case class Binder( } /** One-way match: `pattern` comes from a given's head and may contain type - * variables, `goal` is ground. Unlike `typesOverlap`, which only answers - * yes or no for the coherence check, this records what each variable had to - * be — a conditional given needs those bindings to instantiate its premise. + * variables, `goal` is ground. Unlike `typesOverlap`, which only answers yes + * or no for the coherence check, this records what each variable had to be — + * a conditional given needs those bindings to instantiate its premise. */ def matchType( pattern: Type, @@ -3987,8 +4011,8 @@ case class Binder( } } - /** The two operands of a derived binary member, which - * `builtinBinaryMember` defined as `a` and `b`. + /** The two operands of a derived binary member, which `builtinBinaryMember` + * defined as `a` and `b`. */ def derivedOperands(member: Symbol): Tuple2[Symbol, Symbol] = { filterParameters(member.members()) match { @@ -4026,9 +4050,9 @@ case class Binder( ) /** A call to a given's member. `evidence` is the record it was reached - * through, which every given's member takes as its trailing argument - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). + * through, which every given's member takes as its trailing argument ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). */ def derivedCall( member: Symbol, @@ -4075,9 +4099,9 @@ case class Binder( BoundExpression.EvidenceRecord(noLoc, field, evidenceRecordType) /** `arguments` with the record appended, which every direct call to a given's - * member needs - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). + * member needs ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). * * `None` means resolution failed and reported; the argument is appended * anyway, as an error, so the arity still matches what the callee declares @@ -4105,7 +4129,9 @@ case class Binder( case Option.Some(symbol) => BoundExpression.Variable(noLoc, symbol, Option.Some(evidenceRecordType)) case Option.None => - panic("buildDerivedBody: " + member.name + " has no " + selfEvidenceName) + panic( + "buildDerivedBody: " + member.name + " has no " + selfEvidenceName + ) } } @@ -4114,10 +4140,10 @@ case class Binder( * `Ground` is the case that has always existed: the parameter's type is * concrete, a given proves it outright, and the body calls that given's * member directly with its record. `Through` is what a *generic* type's - * derivation needs — the goal mentions the given's own type variables, so - * it is discharged by the record the member was reached through, and the - * call dispatches rather than naming a target - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md)). + * derivation needs — the goal mentions the given's own type variables, so it + * is discharged by the record the member was reached through, and the call + * dispatches rather than naming a target ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md)). */ enum DerivedEvidence { case Ground(member: Symbol, record: Symbol) @@ -4239,8 +4265,7 @@ case class Binder( case Option.Some(index) => base + index case Option.None => val index = candidate.dependencies.length - candidate.dependencies = - appendConstraint(candidate.dependencies, goal) + candidate.dependencies = appendConstraint(candidate.dependencies, goal) base + index } } @@ -4851,8 +4876,8 @@ case class Binder( * coherence a given in a sibling namespace is still the only candidate, so * it has to be reachable. The declaration site is kept on `BoundGiven` but * does not limit visibility yet — restricting it is what relaxing to true - * lexical scoping would turn on - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * lexical scoping would turn on ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def registerGiven(candidate: BoundGiven): unit = { findOverlappingGiven(candidate, givens) match { @@ -4903,7 +4928,7 @@ case class Binder( */ def evidenceTypes(typ: Type): List[Type] = { enclosingEnumType(typ) match { - case Option.None => ListModule.one(typ) + case Option.None => ListModule.one(typ) case Option.Some(enumTyp) => List.Cons(typ, ListModule.one(enumTyp)) } } @@ -4925,10 +4950,10 @@ case class Binder( * * `enclosingEnumType` answers with the enum as declared, which is enough for * the operator paths: they compare it against a ground receiver and never - * instantiate it. A goal has to keep the arguments — - * `Eq[List.Cons]` widens to `Eq[List]`, not to `Eq[List]` — and a - * case's type parameters are the enum's, in order, because `bindEnumCases` - * passes them straight through. + * instantiate it. A goal has to keep the arguments — `Eq[List.Cons]` + * widens to `Eq[List]`, not to `Eq[List]` — and a case's type + * parameters are the enum's, in order, because `bindEnumCases` passes them + * straight through. */ def widenedEnumType(typ: Type): Option[Type] = { val args = typ match { @@ -5007,7 +5032,13 @@ case class Binder( ) => if (args.length == 1) { Option.Some( - Type.Class(loc, ns, traitName, ListModule.one(operandType), symbol) + Type.Class( + loc, + ns, + traitName, + ListModule.one(operandType), + symbol + ) ) } else Option.None case _ => Option.None @@ -5019,16 +5050,16 @@ case class Binder( * proves it. * * The ground half of operator resolution: where `findEvidenceMember` finds - * evidence held by an enclosing declaration, this finds the given itself. - * A given is a singleton whose members are static, so the caller emits an + * evidence held by an enclosing declaration, this finds the given itself. A + * given is a singleton whose members are static, so the caller emits an * ordinary call rather than dispatching through the record — the record * exists to defer a choice, and here there is nothing left to defer. * * The record still comes back, because the member takes one as its trailing - * argument whether the caller needed it to choose or not - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). Resolving is what interns it: a ground call site is a use, - * and a goal nothing uses gets no record. + * argument whether the caller needed it to choose or not ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). Resolving is what interns it: a ground call site is a use, and a goal + * nothing uses gets no record. */ def findGivenMember( rawGoal: Type, @@ -5069,8 +5100,8 @@ case class Binder( * holds — this answers for a type the givens name directly, so * `value.show()` works on a `Point` and not only inside `[T: Show]`. * - * Only reached once an ordinary lookup has failed, which is what settles - * the shadowing question: a member a type declares itself always wins. + * Only reached once an ordinary lookup has failed, which is what settles the + * shadowing question: a member a type declares itself always wins. */ def findGivenExtension( leftType: Type, @@ -5084,10 +5115,10 @@ case class Binder( * trait applied to `leftType`. * * Matching the head structurally would miss every conditional given, whose - * head holds a type variable: `Show[Box[$0]]` does not equal `Show[Box]` - * and only unification relates them. Going through `findGivenMember` also - * means one place decides which given wins, and one place interns the - * record. + * head holds a type variable: `Show[Box[$0]]` does not equal + * `Show[Box]` and only unification relates them. Going through + * `findGivenMember` also means one place decides which given wins, and one + * place interns the record. */ def scanGivenExtensions( leftType: Type, @@ -5175,8 +5206,8 @@ case class Binder( * `K`. Applying the trait to the variable rather than recording the pair * separately is what lets `Types.substitute` do the work later: substituting * `int` for `$0` turns the constraint into `Eq[int]`, which is exactly the - * goal evidence resolution has to satisfy - * ([ADR 0005](../../../docs/architecture/adr/0005-evidence-representation.md), + * goal evidence resolution has to satisfy ([ADR + * 0005](../../../docs/architecture/adr/0005-evidence-representation.md), * decision E). * * Run this after `bindGenericTypeParameters`, which is what defines the @@ -5203,7 +5234,7 @@ case class Binder( case Option.None => rest case Option.Some(GenericBoundsSyntax(_, name)) => bindContextBound(name, identifier.location, index, scope) match { - case Option.None => rest + case Option.None => rest case Option.Some(constraint) => List.Cons(constraint, rest) } } @@ -5358,11 +5389,10 @@ case class Binder( // Register this object for static constructor creation if it has initialization statements or fields if (allStatements.length > 0 || members.fields.length > 0) { - ctorsToBind = - ctorsToBind.put( - symbol, - ConstructorParams(List.Nil, List.Nil, List.Nil) - ) + ctorsToBind = ctorsToBind.put( + symbol, + ConstructorParams(List.Nil, List.Nil, List.Nil) + ) } } } diff --git a/pncs/src/main/scala/BoundAssemblyPrinter.scala b/pncs/src/main/scala/BoundAssemblyPrinter.scala index faed385..36d5af4 100644 --- a/pncs/src/main/scala/BoundAssemblyPrinter.scala +++ b/pncs/src/main/scala/BoundAssemblyPrinter.scala @@ -73,21 +73,21 @@ class BoundAssemblyPrinter( case expr: BoundExpression.EvidenceCall => printEvidenceCall(expr) case expr: BoundExpression.EvidenceRecord => printEvidenceRecord(expr) - case expr: BoundExpression.Cast => printCastExpression(expr) - case expr: BoundExpression.Character => printCharacterLiteral(expr) - case expr: BoundExpression.For => printForExpression(expr) - case expr: BoundExpression.If => printIfExpression(expr) - case expr: BoundExpression.Index => printIndexExpression(expr) - case expr: BoundExpression.Int => printIntLiteral(expr) - case expr: BoundExpression.Is => printIsExpression(expr) - case expr: BoundExpression.MemberAccess => printMemberAccess(expr) - case expr: BoundExpression.New => printNewExpression(expr) - case expr: BoundExpression.String => printStringLiteral(expr) - case expr: BoundExpression.Unary => printUnaryExpression(expr) - case expr: BoundExpression.Unit => printUnitExpression(expr) - case expr: BoundExpression.Variable => printVariable(expr) - case expr: BoundExpression.While => printWhileExpression(expr) - case expr: BoundExpression.Match => printMatchExpression(expr) + case expr: BoundExpression.Cast => printCastExpression(expr) + case expr: BoundExpression.Character => printCharacterLiteral(expr) + case expr: BoundExpression.For => printForExpression(expr) + case expr: BoundExpression.If => printIfExpression(expr) + case expr: BoundExpression.Index => printIndexExpression(expr) + case expr: BoundExpression.Int => printIntLiteral(expr) + case expr: BoundExpression.Is => printIsExpression(expr) + case expr: BoundExpression.MemberAccess => printMemberAccess(expr) + case expr: BoundExpression.New => printNewExpression(expr) + case expr: BoundExpression.String => printStringLiteral(expr) + case expr: BoundExpression.Unary => printUnaryExpression(expr) + case expr: BoundExpression.Unit => printUnitExpression(expr) + case expr: BoundExpression.Variable => printVariable(expr) + case expr: BoundExpression.While => printWhileExpression(expr) + case expr: BoundExpression.Match => printMatchExpression(expr) } } @@ -181,6 +181,7 @@ class BoundAssemblyPrinter( printExpressions(expr.arguments) writeWithColor(ColorPalette.Punctuation, ")") } + /** Printed as `$ev$K$Eq.equals(a, b)` so the evidence the call dispatches * through is visible, unlike an ordinary call where the target is the name. */ diff --git a/pncs/src/main/scala/BoundNodes.scala b/pncs/src/main/scala/BoundNodes.scala index f404490..f658c53 100644 --- a/pncs/src/main/scala/BoundNodes.scala +++ b/pncs/src/main/scala/BoundNodes.scala @@ -68,6 +68,7 @@ enum BoundLiteral { enum BoundPattern { case Literal(literal: BoundLiteral) case Variable(symbol: Symbol) + /** `case Color.Red =>` — a case named without destructuring it. It binds * nothing, but it is a test, which is why it cannot be a `Discard`. * @@ -75,6 +76,7 @@ enum BoundPattern { * name everywhere this enum is matched on. */ case TypeTest(typ: Type) + /** `case x: int =>` — a test on the annotation, and then whatever the inner * pattern does. Without the test the annotation would be a claim the match * never checks, and `case x: int` would catch everything. @@ -115,6 +117,7 @@ enum BoundExpression { ) case Block(statements: List[BoundStatement], expression: BoundExpression) case Boolean(location: TextLocation, value: bool) + /** A trait member called through evidence. * * Distinct from `Call` because the dispatch target is not a token in the @@ -130,13 +133,14 @@ enum BoundExpression { arguments: List[BoundExpression], resultType: Type ) + /** The static field holding the evidence record that proves a goal. * - * Every call to a given's member carries one as its trailing argument - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). Distinct from a member access because there is no receiver to - * name: the record lives on the program object and the binder holds the - * field directly. + * Every call to a given's member carries one as its trailing argument ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). Distinct from a member access because there is no receiver to name: + * the record lives on the program object and the binder holds the field + * directly. */ case EvidenceRecord(location: TextLocation, field: Symbol, resultType: Type) case Call( diff --git a/pncs/src/main/scala/CompilerSettings.scala b/pncs/src/main/scala/CompilerSettings.scala index 30298c0..100505d 100644 --- a/pncs/src/main/scala/CompilerSettings.scala +++ b/pncs/src/main/scala/CompilerSettings.scala @@ -24,8 +24,8 @@ case class CompilerSettings( printBoundAssembly: bool, printLoweredAssembly: bool, transpile: bool, - /** Compile and execute in one step, instead of emitting. There is no - * output file in this mode — every positional argument is a source. + /** Compile and execute in one step, instead of emitting. There is no output + * file in this mode — every positional argument is a source. */ run: bool ) diff --git a/pncs/src/main/scala/DiagnosticBag.scala b/pncs/src/main/scala/DiagnosticBag.scala index b2af3fd..0cf09cf 100644 --- a/pncs/src/main/scala/DiagnosticBag.scala +++ b/pncs/src/main/scala/DiagnosticBag.scala @@ -248,16 +248,16 @@ case class DiagnosticBag(settings: CompilerSettings) { /** `operator ~(…)`. Only a token the language already parses as a binary * operator may be declared — new syntax comes from a language change, not - * from a library - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * from a library ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ /** `[trace(…)]`. `derive` is the only attribute the language has. */ def reportUnknownAttribute(location: TextLocation, name: string): unit = report(location, name + " is not an attribute") /** `[derive(Eq)] def f() = 1`. Derivation is over constructor parameters, so - * only a class or an enum has anything to derive - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * only a class or an enum has anything to derive ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def reportDeriveNotSupported(location: TextLocation, what: string): unit = report(location, "derive cannot be applied to " + what) @@ -272,9 +272,9 @@ case class DiagnosticBag(settings: CompilerSettings) { name + " cannot be derived; only Eq, Ord and Show can" ) - /** A generic type's derived given is conditional — `Eq[Box[T]]` given - * `Eq[T]` — and a conditional given cannot reach its own premise yet - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + /** A generic type's derived given is conditional — `Eq[Box[T]]` given `Eq[T]` + * — and a conditional given cannot reach its own premise yet ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def reportDeriveOnGenericType(location: TextLocation, name: string): unit = report(location, "Cannot derive for " + name + ": it has type parameters") @@ -301,8 +301,8 @@ case class DiagnosticBag(settings: CompilerSettings) { /** A token belongs to one trait. Without that rule `a == b` would need * overload resolution across traits, and the point of the design is that a - * use site resolves to one piece of evidence - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * use site resolves to one piece of evidence ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def reportOperatorAlreadyClaimed( location: TextLocation, diff --git a/pncs/src/main/scala/Emitter.scala b/pncs/src/main/scala/Emitter.scala index c8ffd8c..6dd9be3 100644 --- a/pncs/src/main/scala/Emitter.scala +++ b/pncs/src/main/scala/Emitter.scala @@ -212,7 +212,7 @@ case class Emitter( map: Dictionary[Symbol, int] ): Dictionary[Symbol, int] = { symbols match { - case List.Nil => map + case List.Nil => map case List.Cons(head, tail) => // Evidence takes an argument slot like a declared parameter; it is a // separate kind only so printers and arity checks can tell them apart. @@ -285,7 +285,7 @@ case class Emitter( def emitMethod(symbol: Symbol, context: EmitContext): bool = { assembly.functionBodies.get(symbol) match { - case Option.None => false + case Option.None => false case Option.Some(value) => // Evidence records first: they are method tokens, so this is the // earliest point they can be built, and everything that reads one runs @@ -381,8 +381,7 @@ case class Emitter( * method tokens, laid out in the trait's declaration order so the reading * side can index it without knowing which given it came from. */ - /** Builds each parameterless enum case once and parks it in its static - * field. + /** Builds each parameterless enum case once and parks it in its static field. * * `Color.Red` names a value rather than making one, so every mention has to * be the same object — otherwise reference identity, which is what `==` @@ -433,8 +432,9 @@ case class Emitter( * The two passes are what make a cycle work rather than an optimisation: * `Eq[Symbol]` points at `Eq[List[Symbol]]`, which points back. Filling as * it goes would need one of them to load a field that has not been stored - * yet ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision E). + * yet ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * E). */ def emitEvidenceRecords( records: List[BoundEvidenceRecord], @@ -504,7 +504,7 @@ case class Emitter( def evidenceTraitMembers(candidate: BoundGiven): List[Symbol] = { binder.getTypeSymbol(candidate.head) match { - case Option.None => List.Nil + case Option.None => List.Nil case Option.Some(traitSymbol) => binder.traitMembers(traitSymbol) } } @@ -846,9 +846,9 @@ case class Emitter( * `Calli` dispatches on the token that comes back. * * The record is loaded twice — once as the member's own trailing argument, - * once to read the token out of - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). The first is what a conditional given reads its premise from. + * once to read the token out of ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). The first is what a conditional given reads its premise from. */ def emitEvidenceCall( expr: LoweredExpression.EvidenceCall, @@ -892,9 +892,9 @@ case class Emitter( /** Evidence reaches a method as its own parameter, as a field on the receiver * in an instance method of a constrained class, or — for a conditional given * reading its own premise — out of the dependency half of the record it was - * reached through - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision D). + * reached through ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * D). */ def emitEvidenceValue( evidence: BoundEvidence, @@ -1012,16 +1012,17 @@ case class Emitter( */ def isCharExpression(expr: LoweredExpression): bool = { expr match { - case _: LoweredExpression.Character => true - case value: LoweredExpression.ArrayAccess => isCharType(value.resultType) - case value: LoweredExpression.BinaryExpression => isCharType(value.resultType) - case value: LoweredExpression.Cast => isCharType(value.resultType) - case value: LoweredExpression.Call => isCharType(value.resultType) - case value: LoweredExpression.EvidenceCall => isCharType(value.resultType) - case value: LoweredExpression.Unary => isCharType(value.resultType) - case value: LoweredExpression.Variable => isCharSymbol(value.symbol) - case value: LoweredExpression.MemberAccess => isCharSymbol(value.symbol) - case _ => false + case _: LoweredExpression.Character => true + case value: LoweredExpression.ArrayAccess => isCharType(value.resultType) + case value: LoweredExpression.BinaryExpression => + isCharType(value.resultType) + case value: LoweredExpression.Cast => isCharType(value.resultType) + case value: LoweredExpression.Call => isCharType(value.resultType) + case value: LoweredExpression.EvidenceCall => isCharType(value.resultType) + case value: LoweredExpression.Unary => isCharType(value.resultType) + case value: LoweredExpression.Variable => isCharSymbol(value.symbol) + case value: LoweredExpression.MemberAccess => isCharSymbol(value.symbol) + case _ => false } } @@ -1329,7 +1330,10 @@ case class Emitter( expr: LoweredExpression.Variable, context: EmitContext ): unit = - emitLoadArgument(context.getParamIndex(expr.symbol), expr.location.startLine) + emitLoadArgument( + context.getParamIndex(expr.symbol), + expr.location.startLine + ) def emitLoadArgument(index: int, line: int): unit = { if (index < 4) { diff --git a/pncs/src/main/scala/ExprBinder.scala b/pncs/src/main/scala/ExprBinder.scala index cf064cf..f43151d 100644 --- a/pncs/src/main/scala/ExprBinder.scala +++ b/pncs/src/main/scala/ExprBinder.scala @@ -985,7 +985,10 @@ case class ExprBinder( /** Whether the right operand widens to the operator member's second * parameter. */ - def operandFits(right: BoundExpression, parameters: List[BoundParameter]): bool = { + def operandFits( + right: BoundExpression, + parameters: List[BoundParameter] + ): bool = { parameters match { case List.Cons(_, List.Cons(second, _)) => conversionClassifier.widensTo(binder.getType(right), second.typ) @@ -997,10 +1000,9 @@ case class ExprBinder( * * `evidence` decides the node: `Some` for a record the caller has to load, * `None` for a static call on the given itself. `record` is the static field - * that call has to pass on as the member's trailing argument - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C); the `EvidenceCall` shape loads its own, so the two are never - * both set. + * that call has to pass on as the member's trailing argument ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C); the `EvidenceCall` shape loads its own, so the two are never both set. */ def bindOperatorCall( location: TextLocation, @@ -1799,7 +1801,9 @@ case class ExprBinder( args, scope ) - case Option.Some(Type.GenericFunction(loc, generics, traits, params, _)) => + case Option.Some( + Type.GenericFunction(loc, generics, traits, params, _) + ) => val typeArgs = if (!explicitTypeArgs.isEmpty) explicitTypeArgs else { diff --git a/pncs/src/main/scala/Lowered.scala b/pncs/src/main/scala/Lowered.scala index cfda760..768a25b 100644 --- a/pncs/src/main/scala/Lowered.scala +++ b/pncs/src/main/scala/Lowered.scala @@ -126,6 +126,7 @@ enum LoweredExpression { arguments: Chain[LoweredExpression], resultType: Type ) + /** A trait member called through evidence. The emitter loads the evidence, * loads the member's token from it, and issues `Calli`; `arguments` already * has the receiver prepended, because a trait declares both operands as @@ -138,6 +139,7 @@ enum LoweredExpression { arguments: Chain[LoweredExpression], resultType: Type ) + /** The static field holding an evidence record, loaded as the trailing * argument of a call to a given's member (ADR 0006, decision C). */ @@ -614,7 +616,10 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { ) case List.Cons(head, tail) => val block = - lowerExpression(head, LoweredBlock(statements, LoweredExpression.Unit)) + lowerExpression( + head, + LoweredBlock(statements, LoweredExpression.Unit) + ) lowerEvidenceCallArguments( call, tail, @@ -1286,9 +1291,9 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { /** One case, as `if () { ; } else `. * - * An irrefutable pattern — `case _` or `case x` — has no test, so it - * becomes the body directly and whatever follows it is unreachable, which - * is what a catch-all means. + * An irrefutable pattern — `case _` or `case x` — has no test, so it becomes + * the body directly and whatever follows it is unreachable, which is what a + * catch-all means. */ def boundMatchCaseToExpression( variable: Symbol, @@ -1299,7 +1304,8 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { val scrutinee: BoundExpression = BoundExpression.Variable(matchCase.location, variable, Option.None) - val bindings = patternBindings(scrutinee, matchCase.pattern, matchCase.location) + val bindings = + patternBindings(scrutinee, matchCase.pattern, matchCase.location) val body: BoundExpression = if (bindings.isEmpty) matchCase.result else BoundExpression.Block(bindings, matchCase.result) @@ -1350,7 +1356,7 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { val test = BoundExpression.Is(location, scrutinee, typ) patternTest(scrutinee, inner, location) match { - case Option.None => Option.Some(test) + case Option.None => Option.Some(test) case Option.Some(innerTest) => // nested, not `&&`-ed: the inner pattern may read the value as the // annotated type, which only the outer test establishes @@ -1408,7 +1414,8 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { fields match { case List.Nil => BoundExpression.Boolean(location, true) case List.Cons(field, tail) => - val rest = subPatternTests(scrutinee, tail, patterns, index + 1, location) + val rest = + subPatternTests(scrutinee, tail, patterns, index + 1, location) if (index >= patterns.length) rest else @@ -1511,13 +1518,13 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { */ def constructorCaseType(constructor: Symbol): Option[Type] = { constructor.parent match { - case Option.None => Option.None + case Option.None => Option.None case Option.Some(owner) => binder.tryGetSymbolType(owner) } } - /** The fields a constructor pattern destructures, in the order its - * parameters are declared. + /** The fields a constructor pattern destructures, in the order its parameters + * are declared. * * Taken from the constructor's parameters rather than from the type's * fields, because a pattern is positional and `members()` gives a class's @@ -1562,8 +1569,8 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { binder.getSymbolType(field) ) - /** A scrutinee as something a member access can hang off. Only the two - * shapes `patternTest` builds ever reach this. + /** A scrutinee as something a member access can hang off. Only the two shapes + * `patternTest` builds ever reach this. */ def asLeftHandSide(expr: BoundExpression): BoundLeftHandSide = { expr match { diff --git a/pncs/src/main/scala/LoweredAssemblyPrinter.scala b/pncs/src/main/scala/LoweredAssemblyPrinter.scala index 094edf0..b8c33a2 100644 --- a/pncs/src/main/scala/LoweredAssemblyPrinter.scala +++ b/pncs/src/main/scala/LoweredAssemblyPrinter.scala @@ -307,8 +307,8 @@ class LoweredAssemblyPrinter( ast.writeWithColor(ColorPalette.String, "'" + string(expr.value) + "'") } - /** `$ev$K$Eq.equals(a, b)` — the evidence is shown because it is the - * dispatch target, not a receiver. + /** `$ev$K$Eq.equals(a, b)` — the evidence is shown because it is the dispatch + * target, not a receiver. */ def printEvidenceCall(call: LoweredExpression.EvidenceCall): unit = { ast.append(evidenceName(call.evidence)) diff --git a/pncs/src/main/scala/Parser.scala b/pncs/src/main/scala/Parser.scala index 49ae67c..f5cec1c 100644 --- a/pncs/src/main/scala/Parser.scala +++ b/pncs/src/main/scala/Parser.scala @@ -482,8 +482,8 @@ case class Parser( /** A context bound: the `Eq` of `[K: Eq]`, meaning the declaration requires * evidence satisfying `Eq[K]`. One bound per parameter — a parameter needing - * two capabilities is not expressible yet - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * two capabilities is not expressible yet ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def parseGenericBounds(): Option[GenericBoundsSyntax] = { debugPrint("parseGenericBounds") @@ -497,9 +497,9 @@ case class Parser( /** `[derive(Eq, Ord, Show)]`, when the member starts with one. * - * Unambiguous at member position: no expression in the language starts - * with `[` — generic arguments and indexing are both postfix — so a - * bracket here can only open an attribute. + * Unambiguous at member position: no expression in the language starts with + * `[` — generic arguments and indexing are both postfix — so a bracket here + * can only open an attribute. */ def parseDeriveAttribute(): Option[DeriveAttributeSyntax] = { if (currentKind() != SyntaxKind.OpenBracketToken) Option.None @@ -1306,9 +1306,9 @@ case class Parser( * `operator` is a contextual keyword, not a reserved one. It cannot be * reserved: the compiler's own sources use `operator` as an identifier 71 * times — `BinaryOperator.operator`, `node.operator` — and `pncs` has to - * compile its own transpiled twin. Three tokens settle it without - * ambiguity, because no member or statement position in those sources - * begins with `operator` followed by an operator token. + * compile its own transpiled twin. Three tokens settle it without ambiguity, + * because no member or statement position in those sources begins with + * `operator` followed by an operator token. */ def isOperatorDeclaration(): bool = current().kind == SyntaxKind.IdentifierToken && @@ -1319,10 +1319,10 @@ case class Parser( /** `operator ==(a: T, b: T): bool` inside a trait or a given. * * The result is an ordinary `FunctionDeclarationSyntax` whose name is the - * operator's own text, so the member binds, types and emits like any other - * — what makes it an operator is which token a trait claims, not a - * different kind of declaration - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * operator's own text, so the member binds, types and emits like any other — + * what makes it an operator is which token a trait claims, not a different + * kind of declaration ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def parseOperatorDeclaration(): MemberSyntax = { debugPrint("parseOperatorDeclaration") diff --git a/pncs/src/main/scala/Program.scala b/pncs/src/main/scala/Program.scala index 967dd87..5808faa 100644 --- a/pncs/src/main/scala/Program.scala +++ b/pncs/src/main/scala/Program.scala @@ -127,15 +127,14 @@ object Program { } } - /** Runs a clean compilation and answers the code the process should end - * with. + /** Runs a clean compilation and answers the code the process should end with. * * A program that chose its own code reports that code; one that failed at * runtime reports 1, there being no code to honour. */ def execute(compilation: Compilation): int = { compilation.exec() match { - case InterpretResult.Exit(code) => code + case InterpretResult.Exit(code) => code case InterpretResult.RuntimeError => 1 case InterpretResult.CompileError => 1 // `Ok` and `OkValue` are both a program that ran to the end. What it diff --git a/pncs/src/main/scala/SymbolKind.scala b/pncs/src/main/scala/SymbolKind.scala index bcc61c4..e3ebcde 100644 --- a/pncs/src/main/scala/SymbolKind.scala +++ b/pncs/src/main/scala/SymbolKind.scala @@ -17,9 +17,9 @@ enum SymbolKind { /** A synthesized parameter carrying the evidence for one context bound. * * Its own kind rather than `Parameter` so printers and arity diagnostics can - * tell it from something the user wrote, while the emitter still allots it an - * argument slot — the mirror of the `This` problem below, which needed to be - * skipped rather than counted. + * tell it from something the user wrote, while the emitter still allots it + * an argument slot — the mirror of the `This` problem below, which needed to + * be skipped rather than counted. */ case Evidence case Alias diff --git a/pncs/src/main/scala/SyntaxFacts.scala b/pncs/src/main/scala/SyntaxFacts.scala index d04029e..5ac35dc 100644 --- a/pncs/src/main/scala/SyntaxFacts.scala +++ b/pncs/src/main/scala/SyntaxFacts.scala @@ -134,11 +134,11 @@ object SyntaxFacts { def isKeywordKind(kind: int): bool = kind >= SyntaxKind.FirstKeyword && kind <= SyntaxKind.LastKeyword - /** Every token in the operator block, which is wider than - * `isBinaryOperator`: `=`, `:`, `.` and `~` are operator tokens that no - * binary expression uses. The parser needs the wider set to recognise - * `operator ~(…)` as an operator declaration at all, so that it can report - * the token as undeclarable rather than fail on a stray member. + /** Every token in the operator block, which is wider than `isBinaryOperator`: + * `=`, `:`, `.` and `~` are operator tokens that no binary expression uses. + * The parser needs the wider set to recognise `operator ~(…)` as an operator + * declaration at all, so that it can report the token as undeclarable rather + * than fail on a stray member. */ def isOperatorKind(kind: int): bool = kind >= SyntaxKind.AmpersandAmpersandToken && diff --git a/pncs/src/main/scala/TypeInference.scala b/pncs/src/main/scala/TypeInference.scala index 8891746..cf8ffee 100644 --- a/pncs/src/main/scala/TypeInference.scala +++ b/pncs/src/main/scala/TypeInference.scala @@ -71,7 +71,8 @@ case class TypeInference(binder: Binder) { // it. Only a result with structure is evidence. Option.None case _ => - val typeMap = inferTypeFromPair(resultType, expectedType, emptyTypeMap()) + val typeMap = + inferTypeFromPair(resultType, expectedType, emptyTypeMap()) if (allSolved(genericParams, typeMap, 0)) { Option.Some(mapGenericParamsToTypes(genericParams, typeMap)) } else { diff --git a/pncs/src/main/scala/VM.scala b/pncs/src/main/scala/VM.scala index 5dc12e7..12445c2 100644 --- a/pncs/src/main/scala/VM.scala +++ b/pncs/src/main/scala/VM.scala @@ -10,9 +10,9 @@ enum InterpretResult { ) // completed running the program and returned a value /** The program called `exit(code)`. * - * Distinct from `OkValue`, which carries the value the program evaluated - * to: `exit(3)` and a program whose last expression is `3` mean different - * things to whatever launched it, and only the first one chose its code. + * Distinct from `OkValue`, which carries the value the program evaluated to: + * `exit(3)` and a program whose last expression is `3` mean different things + * to whatever launched it, and only the first one chose its code. */ case Exit(code: int) case CompileError @@ -334,13 +334,13 @@ case class VM( condition match { case Value.Bool(true) => push(Value.Uninitialized) case Value.Bool(false) => runtimeError(valueToString(message)) - case _ => runtimeError("Expected bool condition for assert") + case _ => runtimeError("Expected bool condition for assert") } } /** `string(value)`. */ def stringApplyOp(): InterpretResult = { - push(Value.String(valueToString(pop()))) + push(Value.String(valueToString(pop()))) } /** `string(c)` where `c` is a char — the character itself, not its code. @@ -360,74 +360,74 @@ case class VM( /** `bool(value)`. */ def boolApplyOp(): InterpretResult = { - val a = pop() - a match { - case Value.Int(0) => - pushBool(false) - InterpretResult.Continue - case Value.Int(_) => - pushBool(true) - InterpretResult.Continue - case Value.Bool(b) => - pushBool(b) - InterpretResult.Continue - case _ => - runtimeError("Cannot convert value to bool: " + string(a)) - } + val a = pop() + a match { + case Value.Int(0) => + pushBool(false) + InterpretResult.Continue + case Value.Int(_) => + pushBool(true) + InterpretResult.Continue + case Value.Bool(b) => + pushBool(b) + InterpretResult.Continue + case _ => + runtimeError("Cannot convert value to bool: " + string(a)) + } } /** `int(value)`. */ def intApplyOp(): InterpretResult = { - val a = pop() - a match { - case Value.Int(i) => - push(Value.Int(i)) - InterpretResult.Continue - case Value.Bool(true) => - push(Value.Int(1)) - InterpretResult.Continue - case Value.Bool(false) => - push(Value.Int(0)) - InterpretResult.Continue - case Value.String(s) => - if (s.length == 0) { - runtimeError("Cannot convert empty string to int") - } else if (s(0) == '-') { - atoi(s, 1, 0) match { - case Option.None => runtimeError("Cannot convert string to int") - case Option.Some(value) => push(Value.Int(-value)) - } - } else { - atoi(s, 0, 0) match { - case Option.None => runtimeError("Cannot convert string to int") - case Option.Some(value) => push(Value.Int(value)) - } + val a = pop() + a match { + case Value.Int(i) => + push(Value.Int(i)) + InterpretResult.Continue + case Value.Bool(true) => + push(Value.Int(1)) + InterpretResult.Continue + case Value.Bool(false) => + push(Value.Int(0)) + InterpretResult.Continue + case Value.String(s) => + if (s.length == 0) { + runtimeError("Cannot convert empty string to int") + } else if (s(0) == '-') { + atoi(s, 1, 0) match { + case Option.None => runtimeError("Cannot convert string to int") + case Option.Some(value) => push(Value.Int(-value)) } + } else { + atoi(s, 0, 0) match { + case Option.None => runtimeError("Cannot convert string to int") + case Option.Some(value) => push(Value.Int(value)) + } + } - case _ => - runtimeError("Cannot convert value to int") - } + case _ => + runtimeError("Cannot convert value to int") + } } /** `char(value)`. */ def charApplyOp(): InterpretResult = { - val a = pop() - a match { - case Value.Int(i) => - push(Value.Int(i)) + val a = pop() + a match { + case Value.Int(i) => + push(Value.Int(i)) + InterpretResult.Continue + case Value.String(s) => + if (s.length == 1) { + push(Value.Int(s(0))) InterpretResult.Continue - case Value.String(s) => - if (s.length == 1) { - push(Value.Int(s(0))) - InterpretResult.Continue - } else { - runtimeError( - "Cannot convert string of length " + string(s.length) + " to char" - ) - } - case _ => - runtimeError("Cannot convert value to char") - } + } else { + runtimeError( + "Cannot convert string of length " + string(s.length) + " to char" + ) + } + case _ => + runtimeError("Cannot convert value to char") + } } /** `compareTo` for every type that has an ordering. diff --git a/pncs/src/main/scala/compilation.scala b/pncs/src/main/scala/compilation.scala index 537a48e..016a6e9 100644 --- a/pncs/src/main/scala/compilation.scala +++ b/pncs/src/main/scala/compilation.scala @@ -72,9 +72,9 @@ case class Compilation( /** The printers, as text. * * `withColor` off is what anything that compares the output wants — a - * snapshot of a coloured tree is a snapshot of the escape codes. The - * builder accumulates rather than printing as it goes, which is the other - * half of being able to hand the result back. + * snapshot of a coloured tree is a snapshot of the escape codes. The builder + * accumulates rather than printing as it goes, which is the other half of + * being able to hand the result back. */ def symbolsText(withColor: bool): string = { val sb = IndentedStringBuilder(false) diff --git a/runtime/src/main/scala/Dictionary.scala b/runtime/src/main/scala/Dictionary.scala index feca127..fe3323a 100644 --- a/runtime/src/main/scala/Dictionary.scala +++ b/runtime/src/main/scala/Dictionary.scala @@ -67,7 +67,7 @@ case class Dictionary[K, V](list: List[KeyValue[K, V]]) { while (!rest.isEmpty) { rest match { - case List.Nil => rest = List.Nil + case List.Nil => rest = List.Nil case List.Cons(kv, next) => // guarded so only the first match goes, matching the recursive // version this replaced diff --git a/test/src/test/scala/BinderTests.scala b/test/src/test/scala/BinderTests.scala index a4b4f60..2339f57 100644 --- a/test/src/test/scala/BinderTests.scala +++ b/test/src/test/scala/BinderTests.scala @@ -130,8 +130,8 @@ class BinderTests extends AnyFunSpec with Matchers { ) shouldBe Seq("Method:==", "Method:!=") } - /** Only `Eq` and `Ord` claim tokens. `Show` declares no operator, so - * `show` stays an ordinary contextual extension (ADR 0004). + /** Only `Eq` and `Ord` claim tokens. `Show` declares no operator, so `show` + * stays an ordinary contextual extension (ADR 0004). */ it("should claim the comparison tokens for the prelude traits") { val comp = mkCompilation("") @@ -673,9 +673,10 @@ class BinderTests extends AnyFunSpec with Matchers { givenHeads(comp) shouldBe Seq("Eqv") } - /** Overlap is unification, not equality: `Ranked[Box[T]]` and `Ranked[Box[int]]` - * are two givens for one pair as soon as `T` can be `int`. Comparing type - * arguments structurally would let this pair through. + /** Overlap is unification, not equality: `Ranked[Box[T]]` and + * `Ranked[Box[int]]` are two givens for one pair as soon as `T` can be + * `int`. Comparing type arguments structurally would let this pair + * through. */ it("should reject a concrete given overlapping a conditional one") { val comp = mkFailingCompilation( @@ -737,12 +738,16 @@ class BinderTests extends AnyFunSpec with Matchers { it("should report a constrained call with no matching given") { val comp = - mkFailingCompilation(eqTrait + eqInt + same + "val r = same(true, false)") + mkFailingCompilation( + eqTrait + eqInt + same + "val r = same(true, false)" + ) diagnosticMessages(comp) should contain("No given instance for Eqv") } it("should leave unconstrained generics alone") { - mkCompilation(eqTrait + eqInt + "def id[K](a: K): K = a\nval r = id(true)") + mkCompilation( + eqTrait + eqInt + "def id[K](a: K): K = a\nval r = id(true)" + ) } /** `TypeInference` carries what it has learned in an immutable @@ -777,8 +782,8 @@ class BinderTests extends AnyFunSpec with Matchers { ) } - /** A constrained class resolves at the `new` site, where its type - * arguments are concrete (ADR 0005, decision B). + /** A constrained class resolves at the `new` site, where its type arguments + * are concrete (ADR 0005, decision B). */ it("should resolve evidence for a constrained constructor") { val setup = eqTrait + eqInt + "class Box[T: Eqv](value: T)\n" @@ -797,7 +802,8 @@ class BinderTests extends AnyFunSpec with Matchers { " def compare(a: Box[T], b: Box[T]): int = 0\n" + "}\n" + "def srt[K: Ranked](a: K): int = 0\n" - val ordInt = "given Ranked[int] { def compare(a: int, b: int): int = 0 }\n" + val ordInt = + "given Ranked[int] { def compare(a: int, b: int): int = 0 }\n" mkCompilation(boxOrd + ordInt + "val r = srt(new Box[int](1))") @@ -805,7 +811,9 @@ class BinderTests extends AnyFunSpec with Matchers { // reported rather than the outer one val comp = mkFailingCompilation(boxOrd + "val r = srt(new Box[int](1))") - diagnosticMessages(comp) should contain("No given instance for Ranked") + diagnosticMessages(comp) should contain( + "No given instance for Ranked" + ) } /** A record is per ground goal, not per given (ADR 0006, decision B), so @@ -866,11 +874,12 @@ class BinderTests extends AnyFunSpec with Matchers { } /** A context bound becomes a parameter appended after the declared ones, so - * every declared parameter keeps the argument slot it already had - * (ADR 0005, decision A). + * every declared parameter keeps the argument slot it already had (ADR + * 0005, decision A). */ it("should append an evidence parameter for a context bound") { - val comp = mkCompilation(eqTrait + "def same[K: Eqv](a: K, b: K): bool = true") + val comp = + mkCompilation(eqTrait + "def same[K: Eqv](a: K, b: K): bool = true") val program = assertSome(comp.root.lookup("$Program")) val same = assertSome(program.lookup("same")) @@ -1065,8 +1074,8 @@ class BinderTests extends AnyFunSpec with Matchers { } /** A given supplies the implementation for a token its trait already owns, - * so it claims nothing of its own — otherwise the second given for a - * trait would collide with the first. + * so it claims nothing of its own — otherwise the second given for a trait + * would collide with the first. */ it("should not let a given claim a token") { mkCompilation( @@ -1098,8 +1107,8 @@ class BinderTests extends AnyFunSpec with Matchers { * not asked for evidence and should not be told about it. * * `<` rather than `==`: ADR 0003's identity rule accepts `==` between two - * unconstrained type parameters, which predates this change and is left - * as it is here. + * unconstrained type parameters, which predates this change and is left as + * it is here. */ it("should reject an operator on an unconstrained type parameter") { val comp = mkFailingCompilation("def lt[T](a: T, b: T): bool = a < b") @@ -1142,8 +1151,8 @@ class BinderTests extends AnyFunSpec with Matchers { } /** ADR 0004's derivation. The attribute declares a given for each trait it - * names, owned by the type's own declaration — which is what satisfies - * the ownership half of coherence for free. + * names, owned by the type's own declaration — which is what satisfies the + * ownership half of coherence for free. */ it("should register a given for each derived trait") { val comp = mkCompilation( @@ -1160,8 +1169,8 @@ class BinderTests extends AnyFunSpec with Matchers { ) shouldBe Seq("Method:<", "Method:<=", "Method:>", "Method:>=") } - /** Nothing is derived without the attribute, so `a == b` on a class with - * no `Eq` still means identity rather than a silent structural compare. + /** Nothing is derived without the attribute, so `a == b` on a class with no + * `Eq` still means identity rather than a silent structural compare. */ it("should derive nothing without the attribute") { val comp = mkCompilation("class Point(x: int, y: int)") @@ -1337,8 +1346,8 @@ class BinderTests extends AnyFunSpec with Matchers { givenHeads(comp) shouldBe Seq("Eq>") } - /** The instantiation still has to have evidence for what it substitutes - * in, and it is the premise that reports when it does not. + /** The instantiation still has to have evidence for what it substitutes in, + * and it is the premise that reports when it does not. * * The annotation is load-bearing: a bare `Opt.Has(true)` infers the case * type, and only the operator and extension paths widen a case to its @@ -1417,9 +1426,8 @@ class BinderTests extends AnyFunSpec with Matchers { mkCompilation(shape + "val r = Shape.Circle(1).show()") } - /** A type whose parameter is another derived type composes: the inner - * given is registered before any body is built, so the outer one finds - * it. + /** A type whose parameter is another derived type composes: the inner given + * is registered before any body is built, so the outer one finds it. */ it("should derive over a parameter that is itself derived") { mkCompilation( diff --git a/test/src/test/scala/CalliTests.scala b/test/src/test/scala/CalliTests.scala index 4e8f405..fab8c49 100644 --- a/test/src/test/scala/CalliTests.scala +++ b/test/src/test/scala/CalliTests.scala @@ -3,9 +3,8 @@ import org.scalatest.funspec.AnyFunSpec import org.scalatest.matchers.should.Matchers /** `Calli` is exercised directly against a hand-built chunk. The emitter does - * not produce one yet, and this is the instruction every call through - * evidence will go through, so it is worth pinning independently of the - * front end. + * not produce one yet, and this is the instruction every call through evidence + * will go through, so it is worth pinning independently of the front end. */ class CalliTests extends AnyFunSpec with Matchers { @@ -61,7 +60,7 @@ class CalliTests extends AnyFunSpec with Matchers { value match { case Value.Int(i) => i shouldBe 42 - case other => throw new AssertionError("expected int, got " + other) + case other => throw new AssertionError("expected int, got " + other) } } diff --git a/test/src/test/scala/ParserTests.scala b/test/src/test/scala/ParserTests.scala index c03292e..1ef6bd2 100644 --- a/test/src/test/scala/ParserTests.scala +++ b/test/src/test/scala/ParserTests.scala @@ -465,7 +465,8 @@ class ParserTests extends AnyFunSpec with Matchers { * language starts with `[` (ADR 0004). */ it("should parse a derive attribute on a class") { - val decl = mkClassMember("[derive(Eq, Ord, Show)]\nclass Point(x: int, y: int)") + val decl = + mkClassMember("[derive(Eq, Ord, Show)]\nclass Point(x: int, y: int)") val attribute = assertSome(decl.derives) assertTokenKind(SyntaxKind.OpenBracketToken, attribute.openBracketToken) diff --git a/test/src/test/scala/PnbTests.scala b/test/src/test/scala/PnbTests.scala index ab6c6aa..463675d 100644 --- a/test/src/test/scala/PnbTests.scala +++ b/test/src/test/scala/PnbTests.scala @@ -36,8 +36,8 @@ class PnbTests extends AnyFunSpec with Matchers { /** The int-to-bytes encoding, on its own. * - * A whole program only happens to contain the values that would expose a - * bad one — a middle byte of 0xFF in an otherwise small number corrupts + * A whole program only happens to contain the values that would expose a bad + * one — a middle byte of 0xFF in an otherwise small number corrupts * everything above it if the sign is not masked off, and no test program * reliably contains one. */ @@ -139,8 +139,8 @@ class PnbTests extends AnyFunSpec with Matchers { assertSameThroughImage("true") } - /** Strings are the table that had no serializer at all, so an image used - * to come back with names for nothing and no literals to load. + /** Strings are the table that had no serializer at all, so an image used to + * come back with names for nothing and no literals to load. */ it("should round-trip string literals") { assertSameThroughImage("\"hello\"") @@ -158,8 +158,8 @@ class PnbTests extends AnyFunSpec with Matchers { assertSameThroughImage("if (1 < 2) 10 else 20") } - /** Fields are the table whose reader strode three ints through - * four-int records. + /** Fields are the table whose reader strode three ints through four-int + * records. */ it("should round-trip a program with classes and fields") { assertSameThroughImage( diff --git a/test/src/test/scala/SampleTests.scala b/test/src/test/scala/SampleTests.scala index 002c817..ed7481f 100644 --- a/test/src/test/scala/SampleTests.scala +++ b/test/src/test/scala/SampleTests.scala @@ -52,7 +52,11 @@ class SampleTests extends AnyFunSpec with Matchers { * no recorded output is untested, and the fix is to run with * `UPDATE_SNAPSHOTS=1` and read what it wrote. */ - private def checkSnapshot(name: String, kind: String, actual: String): Unit = { + private def checkSnapshot( + name: String, + kind: String, + actual: String + ): Unit = { val file = snapshotsDir.resolve(name + "." + kind + ".txt") if (updating) { Files.createDirectories(snapshotsDir) @@ -77,11 +81,11 @@ class SampleTests extends AnyFunSpec with Matchers { } val ending = result match { - case InterpretResult.Exit(code) => "exit " + code - case InterpretResult.RuntimeError => "runtime error" - case InterpretResult.CompileError => "compile error" + case InterpretResult.Exit(code) => "exit " + code + case InterpretResult.RuntimeError => "runtime error" + case InterpretResult.CompileError => "compile error" case InterpretResult.OkValue(value) => "ok" - case _ => "ok" + case _ => "ok" } buffer.toString("utf-8") + "--- " + ending + "\n" @@ -109,11 +113,15 @@ class SampleTests extends AnyFunSpec with Matchers { checkSnapshot(name, "out", runSample(source)) } - /** The binder's answer: every symbol and the type it was given. This - * is where a type that went missing shows up. + /** The binder's answer: every symbol and the type it was given. This is + * where a type that went missing shows up. */ it("should produce the expected symbols") { - checkSnapshot(name, "symbols", mkCompilation(source).symbolsText(false)) + checkSnapshot( + name, + "symbols", + mkCompilation(source).symbolsText(false) + ) } /** The desugaring: `while` to labels and gotos, `match` to tests, diff --git a/test/src/test/scala/TestHelpers.scala b/test/src/test/scala/TestHelpers.scala index 10b7a25..486d2af 100644 --- a/test/src/test/scala/TestHelpers.scala +++ b/test/src/test/scala/TestHelpers.scala @@ -559,9 +559,9 @@ object TestHelpers { symbol.name.startsWith("$given$Ord$") || symbol.name.startsWith("$given$Show$") - /** A static field the binder synthesizes on `$Program`: an evidence record - * or an enum case's singleton. Both are placement details rather than - * anything the source declared. + /** A static field the binder synthesizes on `$Program`: an evidence record or + * an enum case's singleton. Both are placement details rather than anything + * the source declared. */ private def isSynthesizedField(symbol: Symbol): Boolean = symbol.name.startsWith("$case$") @@ -570,8 +570,8 @@ object TestHelpers { * removed. * * Skipping it rather than asserting past it is what keeps a test about - * `val x = 12` from having to be updated whenever the prelude gains a - * given. The prelude has its own tests for what it defines. + * `val x = 12` from having to be updated whenever the prelude gains a given. + * The prelude has its own tests for what it defines. * * The root's own members are matched by name; below the root only the * synthesized fields on `$Program` are, so a source that declares a method diff --git a/test/src/test/scala/TranspilerTests.scala b/test/src/test/scala/TranspilerTests.scala index 88d8e2d..18b60de 100644 --- a/test/src/test/scala/TranspilerTests.scala +++ b/test/src/test/scala/TranspilerTests.scala @@ -7,8 +7,8 @@ import org.scalatest.matchers.should.Matchers * handful of places it rewrites rather than copies. Derivation is the largest * of them: Scala generates structural equality and printing for `case class` * and `enum` alike, Panther has one kind of class, and `[derive(Eq, Show)]` is - * what carries the difference across - * ([ADR 0004](../../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * what carries the difference across ([ADR + * 0004](../../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ class TranspilerTests extends AnyFunSpec with Matchers { @@ -70,8 +70,8 @@ class TranspilerTests extends AnyFunSpec with Matchers { "object Shapes {\n /** a colour */\n [derive(Eq, Show)] enum Color {\n case Red\n }\n}" } - /** Scala's names for the builtins are not Panther's. Only the type - * position is rewritten. + /** Scala's names for the builtins are not Panther's. Only the type position + * is rewritten. */ it("should rewrite Scala's builtin type names") { mkTranspiled("def f(a: String, b: Boolean): Unit = ()") shouldBe @@ -82,10 +82,10 @@ class TranspilerTests extends AnyFunSpec with Matchers { "[derive(Eq, Show)]\nclass Label(name: string)" } - /** The hard half. `String`, `Boolean` and `Unit` are also the names of - * enum cases all over the AST, so rewriting the token wherever it appeared - * — or even the last segment of a qualified type — would rename the - * compiler's own types out from under it. + /** The hard half. `String`, `Boolean` and `Unit` are also the names of enum + * cases all over the AST, so rewriting the token wherever it appeared — or + * even the last segment of a qualified type — would rename the compiler's + * own types out from under it. */ it("should leave a case named String or Unit alone") { mkTranspiled( diff --git a/test/src/test/scala/TypeTests.scala b/test/src/test/scala/TypeTests.scala index beeab9c..9e2a15e 100644 --- a/test/src/test/scala/TypeTests.scala +++ b/test/src/test/scala/TypeTests.scala @@ -862,7 +862,11 @@ class TypeTests extends AnyFunSpec with Matchers { "val one = Chain.One(1)" assertInferExprTypeWithSetup(setup, "one", "Chain.One") - assertAssignableToWithSetup(setup, "Pair(1, one)", "Pair[int, Chain[int]]") + assertAssignableToWithSetup( + setup, + "Pair(1, one)", + "Pair[int, Chain[int]]" + ) } it("should infer constructor type arguments from the expected type") { diff --git a/test/src/test/scala/VmTests.scala b/test/src/test/scala/VmTests.scala index fbb1148..adac476 100644 --- a/test/src/test/scala/VmTests.scala +++ b/test/src/test/scala/VmTests.scala @@ -104,9 +104,9 @@ class VmTests extends AnyFunSpec with Matchers { assertExecValueBoolWithSetup(setup, "same(\"ab\", \"cd\")", false) } - /** A record has one slot per trait member, so calling the second member - * has to read slot 1. Getting the layout wrong would silently call the - * other method, which is why both are exercised. + /** A record has one slot per trait member, so calling the second member has + * to read slot 1. Getting the layout wrong would silently call the other + * method, which is why both are exercised. */ it("should index the right member of a multi-member trait") { val setup = @@ -227,8 +227,8 @@ class VmTests extends AnyFunSpec with Matchers { } /** One trait, four tokens. Each has to reach its own member, which is the - * record-layout question again — with `<` and `>` a swap is visible - * rather than silent. + * record-layout question again — with `<` and `>` a swap is visible rather + * than silent. */ it("should run each prelude comparison operator") { val setup = @@ -247,8 +247,8 @@ class VmTests extends AnyFunSpec with Matchers { assertExecValueBoolWithSetup(setup, "ge(2, 9)", false) } - /** `Show` claims no token, so `show` is reached as a contextual extension - * — and its body is the conversion the language already has. + /** `Show` claims no token, so `show` is reached as a contextual extension — + * and its body is the conversion the language already has. */ it("should run show through prelude evidence") { val setup = "def render[T: Show](value: T): string = value.show()" @@ -262,9 +262,9 @@ class VmTests extends AnyFunSpec with Matchers { * static, so this compiles to an ordinary call rather than a record read. * Both paths have to produce the same answer. * - * This is also what settles evidence beating ADR 0003's identity rule: - * two separately constructed `Box(4)` are different objects, so identity - * would call them unequal. + * This is also what settles evidence beating ADR 0003's identity rule: two + * separately constructed `Box(4)` are different objects, so identity would + * call them unequal. */ it("should run == through a given for a ground type") { val setup = @@ -280,22 +280,42 @@ class VmTests extends AnyFunSpec with Matchers { } /** ADR 0004's derivation, end to end. `Eq` opens with reference identity - * and then compares parameter by parameter, so two separately - * constructed `Point(1, 2)` are equal where identity alone would say no. + * and then compares parameter by parameter, so two separately constructed + * `Point(1, 2)` are equal where identity alone would say no. */ it("should run a derived Eq") { val setup = "[derive(Eq)]\nclass Point(x: int, y: int)" - assertExecValueBoolWithSetup(setup, "new Point(1, 2) == new Point(1, 2)", true) - assertExecValueBoolWithSetup(setup, "new Point(1, 2) == new Point(1, 3)", false) - assertExecValueBoolWithSetup(setup, "new Point(1, 2) == new Point(9, 2)", false) - assertExecValueBoolWithSetup(setup, "new Point(1, 2) != new Point(1, 3)", true) - assertExecValueBoolWithSetup(setup, "new Point(1, 2) != new Point(1, 2)", false) + assertExecValueBoolWithSetup( + setup, + "new Point(1, 2) == new Point(1, 2)", + true + ) + assertExecValueBoolWithSetup( + setup, + "new Point(1, 2) == new Point(1, 3)", + false + ) + assertExecValueBoolWithSetup( + setup, + "new Point(1, 2) == new Point(9, 2)", + false + ) + assertExecValueBoolWithSetup( + setup, + "new Point(1, 2) != new Point(1, 3)", + true + ) + assertExecValueBoolWithSetup( + setup, + "new Point(1, 2) != new Point(1, 2)", + false + ) } /** ADR 0006 step 5: derivation over a generic type. The given is - * conditional, so its body reaches `Eq[T]` through a premise rather than - * a static record, and one declaration serves every instantiation. + * conditional, so its body reaches `Eq[T]` through a premise rather than a + * static record, and one declaration serves every instantiation. */ it("should run a derived Eq over a generic type") { val setup = "[derive(Eq)]\nclass Box[T](value: T)" @@ -362,19 +382,51 @@ class VmTests extends AnyFunSpec with Matchers { it("should run a derived Ord") { val setup = "[derive(Ord)]\nclass Point(x: int, y: int)" - assertExecValueBoolWithSetup(setup, "new Point(1, 2) < new Point(1, 3)", true) - assertExecValueBoolWithSetup(setup, "new Point(1, 3) < new Point(1, 2)", false) - assertExecValueBoolWithSetup(setup, "new Point(1, 9) < new Point(2, 0)", true) - assertExecValueBoolWithSetup(setup, "new Point(2, 2) < new Point(1, 3)", false) - assertExecValueBoolWithSetup(setup, "new Point(1, 2) <= new Point(1, 2)", true) - assertExecValueBoolWithSetup(setup, "new Point(1, 3) > new Point(1, 2)", true) - assertExecValueBoolWithSetup(setup, "new Point(1, 2) >= new Point(1, 2)", true) - assertExecValueBoolWithSetup(setup, "new Point(1, 2) >= new Point(1, 3)", false) + assertExecValueBoolWithSetup( + setup, + "new Point(1, 2) < new Point(1, 3)", + true + ) + assertExecValueBoolWithSetup( + setup, + "new Point(1, 3) < new Point(1, 2)", + false + ) + assertExecValueBoolWithSetup( + setup, + "new Point(1, 9) < new Point(2, 0)", + true + ) + assertExecValueBoolWithSetup( + setup, + "new Point(2, 2) < new Point(1, 3)", + false + ) + assertExecValueBoolWithSetup( + setup, + "new Point(1, 2) <= new Point(1, 2)", + true + ) + assertExecValueBoolWithSetup( + setup, + "new Point(1, 3) > new Point(1, 2)", + true + ) + assertExecValueBoolWithSetup( + setup, + "new Point(1, 2) >= new Point(1, 2)", + true + ) + assertExecValueBoolWithSetup( + setup, + "new Point(1, 2) >= new Point(1, 3)", + false + ) } /** `"Name(" + show(p1) + ", " + … + ")"`, reached through a constrained - * generic — `Show` claims no token, and a contextual extension on a - * ground type is a gap ADR 0004 records. + * generic — `Show` claims no token, and a contextual extension on a ground + * type is a gap ADR 0004 records. */ it("should run a derived Show") { val render = "def render[T: Show](v: T): string = v.show()\n" @@ -566,10 +618,10 @@ class VmTests extends AnyFunSpec with Matchers { ) } - /** A parameter whose type is a composite over the type variable — - * `Lst[T]` inside `Holder[T]` — is neither ground nor a declared premise, - * so it becomes a premise of its own, filled per instantiation. This is - * the shape the AST's own containers have. + /** A parameter whose type is a composite over the type variable — `Lst[T]` + * inside `Holder[T]` — is neither ground nor a declared premise, so it + * becomes a premise of its own, filled per instantiation. This is the + * shape the AST's own containers have. */ it("should run a derived Eq over a composite of a type parameter") { val setup = "[derive(Eq)]\n" + @@ -699,14 +751,22 @@ class VmTests extends AnyFunSpec with Matchers { * `Shape(7)`. */ it("should run a derived Show over an enum") { - assertExecValueStringWithSetup(shape, "Shape.Circle(7).show()", "Circle(7)") - assertExecValueStringWithSetup(shape, "Shape.Rect(1, 2).show()", "Rect(1, 2)") + assertExecValueStringWithSetup( + shape, + "Shape.Circle(7).show()", + "Circle(7)" + ) + assertExecValueStringWithSetup( + shape, + "Shape.Rect(1, 2).show()", + "Rect(1, 2)" + ) } - /** A case with no parameters is one value, not a constructor: every - * mention of `Color.Red` is the same object, built once in - * `$runtimeInit`. Without that, reference identity — which is what `==` - * falls back to with no evidence — would call two of them different. + /** A case with no parameters is one value, not a constructor: every mention + * of `Color.Red` is the same object, built once in `$runtimeInit`. Without + * that, reference identity — which is what `==` falls back to with no + * evidence — would call two of them different. */ val color = "enum Color {\n case Red\n case Green\n case Blue\n}\n" @@ -1076,8 +1136,8 @@ class VmTests extends AnyFunSpec with Matchers { ) } - /** A bare name binds the scrutinee and always matches, so it is a - * catch-all that can also be read. + /** A bare name binds the scrutinee and always matches, so it is a catch-all + * that can also be read. */ it("should bind a variable pattern to the scrutinee") { assertExecValueIntWithSetup( @@ -1158,19 +1218,20 @@ class VmTests extends AnyFunSpec with Matchers { * its binding reads a field of a field. */ it("should match a nested extract pattern") { - val setup = "enum Option[out T] {\n case Some(value: T)\n case None\n}\n" + - "def f(o: Option[Option[int]]): int = o match {\n" + - " case Option.Some(Option.Some(v)) => v\n" + - " case Option.Some(Option.None) => -1\n" + - " case Option.None => -2\n}\n" + val setup = + "enum Option[out T] {\n case Some(value: T)\n case None\n}\n" + + "def f(o: Option[Option[int]]): int = o match {\n" + + " case Option.Some(Option.Some(v)) => v\n" + + " case Option.Some(Option.None) => -1\n" + + " case Option.None => -2\n}\n" assertExecValueIntWithSetup(setup, "f(Option.Some(Option.Some(5)))", 5) assertExecValueIntWithSetup(setup, "f(Option.Some(Option.None))", -1) assertExecValueIntWithSetup(setup, "f(Option.None)", -2) } - /** The annotation on `case x: int` is a test as well as a type. Without - * it the first annotated case caught everything. + /** The annotation on `case x: int` is a test as well as a type. Without it + * the first annotated case caught everything. */ it("should test a type assertion pattern") { val setup = "def f(v: any): string = v match {\n" + @@ -1444,8 +1505,8 @@ class VmTests extends AnyFunSpec with Matchers { * runs, so it cannot tell them apart from the value — the emitter picks * between two builtins by the static type. Before that, `string('a')` * answered "97", which quietly broke every string built a character at a - * time: `StringBuilder.appendChar`, `Hex.toString`, and the lexer's - * escape handling. + * time: `StringBuilder.appendChar`, `Hex.toString`, and the lexer's escape + * handling. */ it("should convert a char to the character it names") { assertExecValueString("string('a')", "a") @@ -1575,9 +1636,21 @@ class VmTests extends AnyFunSpec with Matchers { } it("should execute substring") { - assertExecValueStringWithSetup("val s = \"hello\"", "s.substring(1, 3)", "el") - assertExecValueStringWithSetup("val s = \"hello\"", "s.substring(0, 5)", "hello") - assertExecValueStringWithSetup("val s = \"hello\"", "s.substring(2, 2)", "") + assertExecValueStringWithSetup( + "val s = \"hello\"", + "s.substring(1, 3)", + "el" + ) + assertExecValueStringWithSetup( + "val s = \"hello\"", + "s.substring(0, 5)", + "hello" + ) + assertExecValueStringWithSetup( + "val s = \"hello\"", + "s.substring(2, 2)", + "" + ) assertExecValueStringWithSetup( "val s = \"hello\"", "s.substring(1, s.length)", @@ -1586,9 +1659,21 @@ class VmTests extends AnyFunSpec with Matchers { } it("should execute endsWith") { - assertExecValueBoolWithSetup("val s = \"a.scala\"", "s.endsWith(\".scala\")", true) - assertExecValueBoolWithSetup("val s = \"a.scala\"", "s.endsWith(\".pn\")", false) - assertExecValueBoolWithSetup("val s = \"a.scala\"", "s.endsWith(\"\")", true) + assertExecValueBoolWithSetup( + "val s = \"a.scala\"", + "s.endsWith(\".scala\")", + true + ) + assertExecValueBoolWithSetup( + "val s = \"a.scala\"", + "s.endsWith(\".pn\")", + false + ) + assertExecValueBoolWithSetup( + "val s = \"a.scala\"", + "s.endsWith(\"\")", + true + ) } /** `compareTo` answers the sign, not the difference, and one opcode serves From dbed4fc21abfd777fe1ee2f91ccb353e7b5a72dc Mon Sep 17 00:00:00 2001 From: Kevin Thompson Date: Tue, 8 Sep 2026 22:17:14 -0700 Subject: [PATCH 2/2] fix(transpiler): regenerate pnc/src after scalafmt reformat The transpile CI job re-runs pncs/transpile and diffs the result, so the .pn outputs need to match the reformatted Scala sources. Co-Authored-By: Claude Sonnet 5 --- pnc/src/Ast.pn | 28 +-- pnc/src/AstPrinter.pn | 5 +- pnc/src/BinaryOperators.pn | 7 +- pnc/src/Binder.pn | 284 +++++++++++++++++------------- pnc/src/BoundAssemblyPrinter.pn | 31 ++-- pnc/src/BoundNodes.pn | 14 +- pnc/src/Builtin.pn | 42 ++--- pnc/src/CompilerSettings.pn | 4 +- pnc/src/DiagnosticBag.pn | 18 +- pnc/src/Dictionary.pn | 2 +- pnc/src/Emitter.pn | 52 +++--- pnc/src/ExprBinder.pn | 16 +- pnc/src/Lowered.pn | 31 ++-- pnc/src/LoweredAssemblyPrinter.pn | 4 +- pnc/src/Metadata.pn | 4 +- pnc/src/Opcode.pn | 6 +- pnc/src/Parser.pn | 24 +-- pnc/src/Program.pn | 5 +- pnc/src/SymbolKind.pn | 6 +- pnc/src/SyntaxFacts.pn | 10 +- pnc/src/TypeInference.pn | 3 +- pnc/src/VM.pn | 124 ++++++------- pnc/src/compilation.pn | 6 +- 23 files changed, 391 insertions(+), 335 deletions(-) diff --git a/pnc/src/Ast.pn b/pnc/src/Ast.pn index ae90afd..6f7f8f5 100644 --- a/pnc/src/Ast.pn +++ b/pnc/src/Ast.pn @@ -272,8 +272,8 @@ class GenericParametersSyntax( [derive(Eq, Show)] class SeparatedSyntaxList[T](items: List[T], separators: List[SyntaxToken]) -/** One trait named inside a `derive` attribute, with the comma that follows - * it, if any — the same shape `ParameterSyntax` uses for its list. +/** One trait named inside a `derive` attribute, with the comma that follows it, + * if any — the same shape `ParameterSyntax` uses for its list. */ [derive(Eq, Show)] class DerivedTraitSyntax( @@ -283,9 +283,9 @@ class DerivedTraitSyntax( /** `[derive(Eq, Ord, Show)]` ahead of a class or enum. * - * Derivation is opt-in: a type with no attribute gets no evidence, so `a == - * b` on it is a diagnostic rather than a silent identity comparison - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * Derivation is opt-in: a type with no attribute gets no evidence, so `a == b` + * on it is a diagnostic rather than a silent identity comparison ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ [derive(Eq, Show)] class DeriveAttributeSyntax( @@ -324,10 +324,12 @@ class DeriveAttributeSyntax( typeAnnotation: Option[TypeAnnotationSyntax], body: Option[FunctionBodySyntax] ) + /** A trait declares a capability: a name, its type parameters, and the * members an instance has to supply. It has no constructor parameters * because a trait is never instantiated — evidence for it comes from a - * `given` ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * `given` ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ case TraitDeclarationSyntax( traitKeyword: SyntaxToken, @@ -335,13 +337,15 @@ class DeriveAttributeSyntax( genericParameters: Option[GenericParametersSyntax], template: TemplateSyntax ) + /** `given Eq[int] { … }`, or with a premise, * `given [T: Ord] => Ord[List[T]] { … }`. * * The type parameters and the `=>` travel together: a given with nothing to * bind has neither. There is no name — under global coherence there is one * given per `(trait, type)` pair, so a name would have nothing to select - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ case GivenDeclarationSyntax( givenKeyword: SyntaxToken, @@ -566,13 +570,13 @@ object AstUtils { locationOfBoundExpression(left).merge(locationOfBoundExpression(right)) case BoundExpression.Block(statements, expression) => locationOfBoundExpression(expression) - case BoundExpression.Boolean(location, _) => location - case BoundExpression.Call(location, _, _, _, _, _) => location + case BoundExpression.Boolean(location, _) => location + case BoundExpression.Call(location, _, _, _, _, _) => location case BoundExpression.EvidenceCall(location, _, _, _, _) => location case BoundExpression.EvidenceRecord(location, _, _) => location - case BoundExpression.Cast(location, expression, _) => location - case BoundExpression.Character(location, _) => location - case BoundExpression.For(location, _, _, _, _) => location + case BoundExpression.Cast(location, expression, _) => location + case BoundExpression.Character(location, _) => location + case BoundExpression.For(location, _, _, _, _) => location case BoundExpression.If( location, cond, diff --git a/pnc/src/AstPrinter.pn b/pnc/src/AstPrinter.pn index c8ff259..dee0f6c 100644 --- a/pnc/src/AstPrinter.pn +++ b/pnc/src/AstPrinter.pn @@ -137,8 +137,9 @@ class AstPrinter(withColor: bool, buffer: IndentedStringBuilder) { case Option.Some(value) => printGenericParameters(value) } node.arrowToken match { - case Option.None => () - case Option.Some(value) => printTokenWithColor(value, ColorPalette.Keyword) + case Option.None => () + case Option.Some(value) => + printTokenWithColor(value, ColorPalette.Keyword) } printName(node.name) printTemplate(node.template) diff --git a/pnc/src/BinaryOperators.pn b/pnc/src/BinaryOperators.pn index 34fdac0..c9a3c87 100644 --- a/pnc/src/BinaryOperators.pn +++ b/pnc/src/BinaryOperators.pn @@ -116,8 +116,8 @@ class BinaryOperators(binder: Binder) { * question the caller asks last, because evidence has to come first: a type * with `Eq` evidence must compare through that evidence rather than by * identity, and folding the identity rule in here would answer before the - * evidence was ever consulted - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * evidence was ever consulted ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def checkBinary( left: Type, @@ -125,7 +125,8 @@ class BinaryOperators(binder: Binder) { operator: BinaryOperatorKind ): Type = _checkBinary(binaryOps, left, right, operator) - /** [ADR 0003](../../../docs/architecture/adr/0003-equality-on-reference-types.md)'s + /** [ADR + * 0003](../../../docs/architecture/adr/0003-equality-on-reference-types.md)'s * rule, now the last resort rather than part of the table lookup. */ def referenceEquality( diff --git a/pnc/src/Binder.pn b/pnc/src/Binder.pn index 4124a77..c8fd7e7 100644 --- a/pnc/src/Binder.pn +++ b/pnc/src/Binder.pn @@ -46,12 +46,12 @@ class Namespaced[A](ns: List[string], value: A) /** A resolved proof, and the static field its record lives in. * * One per ground goal rather than one per given, because a conditional given - * proves a different thing at every instantiation - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision B). `premises` are the given's constraints with this - * instantiation's type arguments substituted in, so they are ground goals too - * and name the records the dependency half points at — `Eq[List[Symbol]]` - * holding a reference to `Eq[Symbol]`, which is ADR 0005's recursive evidence. + * proves a different thing at every instantiation ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * B). `premises` are the given's constraints with this instantiation's type + * arguments substituted in, so they are ground goals too and name the records + * the dependency half points at — `Eq[List[Symbol]]` holding a reference to + * `Eq[Symbol]`, which is ADR 0005's recursive evidence. */ [derive(Eq, Show)] class BoundEvidenceRecord( @@ -72,11 +72,11 @@ class BoundEvidenceRecord( /** A given's member, resolved for a particular goal. * * `record` is what proves that goal, which the caller passes as the member's - * trailing argument - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). `typeArguments` are what instantiated the given: a conditional - * given's member is declared in that given's own type variables, so a caller - * has to substitute before it can check operands against the signature. + * trailing argument ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). `typeArguments` are what instantiated the given: a conditional given's + * member is declared in that given's own type variables, so a caller has to + * substitute before it can check operands against the signature. */ [derive(Eq, Show)] class GivenMember( @@ -107,8 +107,8 @@ class BoundGiven( * A derived body over `items: List[T]` needs `Eq[List[$0]]`, which is * neither ground — so no static record proves it — nor one of the declared * premises. It becomes a dependency of this given instead, resolved per - * instantiation exactly as a premise is - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md)). + * instantiation exactly as a premise is ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md)). * * Growable, and read rather than snapshotted everywhere, because a body is * built after the records that will hold its slots have been interned. @@ -121,8 +121,8 @@ class BoundGiven( * The two halves happen in different passes because they need different * things: registering needs only the type, so that coherence sees the given * and evidence records can be laid out, while a body reads the constructor - * parameters' field types, which are not bound until later - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * parameters' field types, which are not bound until later ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ [derive(Eq, Show)] class Derivation( @@ -138,10 +138,9 @@ class Derivation( /** One case of an enum being derived for, in declaration order. * * A class's derivation has no cases and reads `parameterNames`; an enum's has - * a case per alternative and no parameters of its own. The order is the - * enum's own, which is what `Ord` compares by before it looks at any - * parameter - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * a case per alternative and no parameters of its own. The order is the enum's + * own, which is what `Ord` compares by before it looks at any parameter ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ [derive(Eq, Show)] class DerivedCase( @@ -478,9 +477,10 @@ class Binder( /** `system.io`, which the Scala side shims in * [`panther.scala`](../../../../runtime/src/main/scala/panther.scala) — the - * one file `sbt pncs/transpile` skips ([`build.sbt:43`](../../../../build.sbt:43)), - * so there is no generated `.pn` for these to bind to and they have to be - * declared here like the rest of the prelude. + * one file `sbt pncs/transpile` skips + * ([`build.sbt:43`](../../../../build.sbt:43)), so there is no generated + * `.pn` for these to bind to and they have to be declared here like the rest + * of the prelude. * * At the root rather than under a `system.io` namespace, because the binder * does not bind `using` directives at all: they are parsed, printed and @@ -520,7 +520,13 @@ class Binder( ListModule.one( Tuple2( "bytes", - Type.Class(noLoc, List.Nil, "Array", ListModule.one(intType), arraySymbol) + Type.Class( + noLoc, + List.Nil, + "Array", + ListModule.one(intType), + arraySymbol + ) ) ) ), @@ -613,7 +619,8 @@ class Binder( * * A token may be claimed by at most one trait, so that `a == b` resolves to * one piece of evidence rather than needing overload resolution across - * traits ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * traits ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). * * Keyed by token kind rather than by text: a kind has exactly one spelling, * while `SyntaxFacts.getBinaryOperatorText` gives `&&` for both `LogicalAnd` @@ -624,10 +631,10 @@ class Binder( /** Every evidence record the program needs, in reverse discovery order. * * Interned as resolution reaches each ground goal, rather than laid out once - * per given: a conditional given has no single record to lay out - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision B). Discovery order is a function of the source, which is what - * stage 3 needs — the field order is part of the bytecode. + * per given: a conditional given has no single record to lay out ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * B). Discovery order is a function of the source, which is what stage 3 + * needs — the field order is part of the bytecode. * * Each holds a static field on the program object; the emitter fills the * slots, being the first place method tokens are known. @@ -669,10 +676,10 @@ class Binder( /** The record's element type is `any` rather than `int` because the slots * hold two kinds of thing: a method token in the token half, and a reference - * to another record in the dependency half - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision A). The VM's array is untyped — the element type only picks a - * default value — so this costs nothing at runtime. + * to another record in the dependency half ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * A). The VM's array is untyped — the element type only picks a default + * value — so this costs nothing at runtime. */ val evidenceRecordType: Type = Type.Class( @@ -789,16 +796,20 @@ class Binder( val value = param(symbol, "value", operand) setSymbolType( symbol, - Type.Function(noLoc, ListModule.one(BoundParameter(value, operand)), result) + Type.Function( + noLoc, + ListModule.one(BoundParameter(value, operand)), + result + ) ) defineSelfEvidence(symbol) symbol } /** Every member of a given takes the record it was reached through, whether - * or not that given has premises - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). + * or not that given has premises ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). * * Uniform because `Calli` is: the VM reads the argument count from the * *callee's* metadata, and a caller dispatching on a token it read out of a @@ -810,8 +821,8 @@ class Binder( * in `Type.Function.parameters` both leave it out — the arity a diagnostic * reports is still the one the source wrote (ADR 0005, decision E). * - * A trait's own members go through the same two builders and are not - * given members, which is what the owner check is for. + * A trait's own members go through the same two builders and are not given + * members, which is what the owner check is for. */ def defineSelfEvidence(member: Symbol): unit = { member.parent match { @@ -819,7 +830,7 @@ class Binder( case Option.Some(owner) => if (owner.kind == SymbolKind.Given) { member.tryDefineEvidence(selfEvidenceName, member.location) match { - case Either.Left(_) => () + case Either.Left(_) => () case Either.Right(symbol) => // Typed as what the given proves, not as the record's own // `Array[any]`. The value is the same either way — the emitter @@ -848,8 +859,8 @@ class Binder( /** Registers a prelude given and returns its symbol. * * Named after what it proves rather than numbered. `bindGiven` numbers the - * givens it binds so that the numbering is deterministic across compilers; - * a prelude given is already deterministic, and a name keeps the user's + * givens it binds so that the numbering is deterministic across compilers; a + * prelude given is already deterministic, and a name keeps the user's * `$given$0` the first one they wrote. */ def builtinGiven(traitSymbol: Symbol, typ: Type, typeName: string): Symbol = { @@ -874,9 +885,9 @@ class Binder( /** A prelude given's member, whose body is the operator the builtin table * already has a row for: `Eq[int].==` is `a == b` on two ints. * - * The body is a bound expression rather than parsed source, so it skips - * type checking — which is the point, since the check it would go through - * is the one that sends `a == b` back here looking for evidence. + * The body is a bound expression rather than parsed source, so it skips type + * checking — which is the point, since the check it would go through is the + * one that sends `a == b` back here looking for evidence. */ def builtinBinaryBody( owner: Symbol, @@ -992,7 +1003,11 @@ class Binder( ) ) - def declareLocal(symbol: Symbol, typ: Type, init: BoundExpression): BoundStatement = + def declareLocal( + symbol: Symbol, + typ: Type, + init: BoundExpression + ): BoundStatement = BoundStatement.VariableDeclaration(symbol, false, typ, init) def arrayLengthOf(array: Symbol): BoundExpression = @@ -1254,7 +1269,13 @@ class Binder( BinaryOperatorKind.LessThanOrEqual, boolType ) - builtinBinaryBody(symbol, ">", typ, BinaryOperatorKind.GreaterThan, boolType) + builtinBinaryBody( + symbol, + ">", + typ, + BinaryOperatorKind.GreaterThan, + boolType + ) builtinBinaryBody( symbol, ">=", @@ -1325,7 +1346,7 @@ class Binder( parameters: List[Tuple2[string, Type]] ): List[BoundParameter] = parameters match { - case List.Nil => List.Nil + case List.Nil => List.Nil case List.Cons(Tuple2(name, typ), rest) => // The head is defined before the tail is walked, so the parameters end // up in the order they were written. @@ -1809,19 +1830,19 @@ class Binder( case _: BoundExpression.Unit => unitType case _: BoundExpression.While => unitType - case expr: BoundExpression.ArrayCreation => expr.resultType + case expr: BoundExpression.ArrayCreation => expr.resultType case expr: BoundExpression.EvidenceCall => expr.resultType case expr: BoundExpression.EvidenceRecord => expr.resultType - case expr: BoundExpression.Binary => expr.resultType - case expr: BoundExpression.Block => getType(expr.expression) - case expr: BoundExpression.Call => expr.resultType - case expr: BoundExpression.Cast => expr.targetType - case expr: BoundExpression.Index => expr.resultType - case expr: BoundExpression.If => expr.resultType - case expr: BoundExpression.Match => expr.resultType - case expr: BoundExpression.MemberAccess => expr.resultType - case expr: BoundExpression.New => expr.resultType - case expr: BoundExpression.Unary => expr.resultType + case expr: BoundExpression.Binary => expr.resultType + case expr: BoundExpression.Block => getType(expr.expression) + case expr: BoundExpression.Call => expr.resultType + case expr: BoundExpression.Cast => expr.targetType + case expr: BoundExpression.Index => expr.resultType + case expr: BoundExpression.If => expr.resultType + case expr: BoundExpression.Match => expr.resultType + case expr: BoundExpression.MemberAccess => expr.resultType + case expr: BoundExpression.New => expr.resultType + case expr: BoundExpression.Unary => expr.resultType case expr: BoundExpression.Variable => expr.resultType match { case Option.None => getSymbolType(expr.symbol) @@ -2885,9 +2906,9 @@ class Binder( } } - /** Only the prelude's three traits can be derived: derivation is a rule - * about what each of them means over a list of parameters, and there is no - * such rule for a trait the compiler has never seen. + /** Only the prelude's three traits can be derived: derivation is a rule about + * what each of them means over a list of parameters, and there is no such + * rule for a trait the compiler has never seen. */ def derivableTrait(name: string): Option[Symbol] = { if (name == "Eq") Option.Some(eqSymbol) @@ -3211,10 +3232,10 @@ class Binder( * for `leftType`. * * The premise is not a symbol — it is a slot in the dependency half of the - * record the member was reached through - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision D), which is what `scanEvidenceMembers` cannot find by walking - * members. Inside `given [T: Ord] => Ord[Box[T]]`, `a.value.compare(b.value)` + * record the member was reached through ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * D), which is what `scanEvidenceMembers` cannot find by walking members. + * Inside `given [T: Ord] => Ord[Box[T]]`, `a.value.compare(b.value)` * resolves `compare` here. * * Only a method directly inside a given has one, which is what the @@ -3311,7 +3332,7 @@ class Binder( */ def evidenceGoal(evidence: BoundEvidence): Type = { evidence match { - case BoundEvidence.Held(symbol) => getSymbolType(symbol) + case BoundEvidence.Held(symbol) => getSymbolType(symbol) case BoundEvidence.Premise(_, _, goal) => goal } } @@ -3322,7 +3343,7 @@ class Binder( members: List[Symbol] ): Option[KeyValue[BoundEvidence, Symbol]] = { members match { - case List.Nil => Option.None + case List.Nil => Option.None case List.Cons(head, tail) => // Evidence reaches a body two ways: as its own parameter, or as the // field a constrained class stores its constructor's evidence in. The @@ -3333,9 +3354,8 @@ class Binder( // annotated: the self-hosted compiler does not widen the branches of // an `if` to their common supertype val found: Option[KeyValue[BoundEvidence, Symbol]] = - if ( - head.kind != SymbolKind.Evidence && head.kind != SymbolKind.Field - ) Option.None + if (head.kind != SymbolKind.Evidence && head.kind != SymbolKind.Field) + Option.None else tryGetSymbolType(head) match { case Option.Some( @@ -3368,8 +3388,8 @@ class Binder( * last and both `getMethodParameterMap` and metadata emission give them the * trailing argument slots. Appending rather than prepending is what keeps * every declared parameter at the slot it already had — the VM reserves slot - * 0 for the receiver and numbers declared parameters from 1 - * ([ADR 0005](../../../docs/architecture/adr/0005-evidence-representation.md), + * 0 for the receiver and numbers declared parameters from 1 ([ADR + * 0005](../../../docs/architecture/adr/0005-evidence-representation.md), * decision A). * * Order is type-parameter declaration order, which `bindGenericConstraints` @@ -3383,7 +3403,7 @@ class Binder( scope: Scope ): List[Symbol] = { constraints match { - case List.Nil => List.Nil + case List.Nil => List.Nil case List.Cons(constraint, tail) => // define before recursing: `symbol.members()` is in definition order, // and that order is the argument slot order @@ -3526,7 +3546,11 @@ class Binder( case List.Nil => acc case List.Cons(head, tail) => val separator = if (acc == "") "" else ", " - renderGoalList(tail, generics, acc + separator + renderGoal(head, generics)) + renderGoalList( + tail, + generics, + acc + separator + renderGoal(head, generics) + ) } } @@ -3605,11 +3629,11 @@ class Binder( def isGroundType(typ: Type): bool = { typ match { - case Type.Variable(_, _) => false - case Type.Class(_, _, _, args, _) => isGroundTypeList(args) + case Type.Variable(_, _) => false + case Type.Class(_, _, _, args, _) => isGroundTypeList(args) case Type.Alias(_, _, _, args, _, _) => isGroundTypeList(args) - case Type.Union(_, cases) => isGroundTypeList(cases) - case _ => true + case Type.Union(_, cases) => isGroundTypeList(cases) + case _ => true } } @@ -3632,9 +3656,9 @@ class Binder( * needs `Eq[List[Symbol]]`, which needs `Eq[Symbol]` again and finds the * record already being built. ADR 0005 asks for exactly that rule, and it * costs nothing here because a record is an array — a reference to one that - * is allocated but not yet filled is still a usable reference - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision E). + * is allocated but not yet filled is still a usable reference ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * E). */ def resolveEvidence( rawGoal: Type, @@ -3791,9 +3815,9 @@ class Binder( } /** One-way match: `pattern` comes from a given's head and may contain type - * variables, `goal` is ground. Unlike `typesOverlap`, which only answers - * yes or no for the coherence check, this records what each variable had to - * be — a conditional given needs those bindings to instantiate its premise. + * variables, `goal` is ground. Unlike `typesOverlap`, which only answers yes + * or no for the coherence check, this records what each variable had to be — + * a conditional given needs those bindings to instantiate its premise. */ def matchType( pattern: Type, @@ -3996,8 +4020,8 @@ class Binder( } } - /** The two operands of a derived binary member, which - * `builtinBinaryMember` defined as `a` and `b`. + /** The two operands of a derived binary member, which `builtinBinaryMember` + * defined as `a` and `b`. */ def derivedOperands(member: Symbol): Tuple2[Symbol, Symbol] = { filterParameters(member.members()) match { @@ -4035,9 +4059,9 @@ class Binder( ) /** A call to a given's member. `evidence` is the record it was reached - * through, which every given's member takes as its trailing argument - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). + * through, which every given's member takes as its trailing argument ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). */ def derivedCall( member: Symbol, @@ -4084,9 +4108,9 @@ class Binder( BoundExpression.EvidenceRecord(noLoc, field, evidenceRecordType) /** `arguments` with the record appended, which every direct call to a given's - * member needs - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). + * member needs ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). * * `None` means resolution failed and reported; the argument is appended * anyway, as an error, so the arity still matches what the callee declares @@ -4114,7 +4138,9 @@ class Binder( case Option.Some(symbol) => BoundExpression.Variable(noLoc, symbol, Option.Some(evidenceRecordType)) case Option.None => - panic("buildDerivedBody: " + member.name + " has no " + selfEvidenceName) + panic( + "buildDerivedBody: " + member.name + " has no " + selfEvidenceName + ) } } @@ -4123,10 +4149,10 @@ class Binder( * `Ground` is the case that has always existed: the parameter's type is * concrete, a given proves it outright, and the body calls that given's * member directly with its record. `Through` is what a *generic* type's - * derivation needs — the goal mentions the given's own type variables, so - * it is discharged by the record the member was reached through, and the - * call dispatches rather than naming a target - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md)). + * derivation needs — the goal mentions the given's own type variables, so it + * is discharged by the record the member was reached through, and the call + * dispatches rather than naming a target ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md)). */ [derive(Eq, Show)] enum DerivedEvidence { case Ground(member: Symbol, record: Symbol) @@ -4248,8 +4274,7 @@ class Binder( case Option.Some(index) => base + index case Option.None => val index = candidate.dependencies.length - candidate.dependencies = - appendConstraint(candidate.dependencies, goal) + candidate.dependencies = appendConstraint(candidate.dependencies, goal) base + index } } @@ -4860,8 +4885,8 @@ class Binder( * coherence a given in a sibling namespace is still the only candidate, so * it has to be reachable. The declaration site is kept on `BoundGiven` but * does not limit visibility yet — restricting it is what relaxing to true - * lexical scoping would turn on - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * lexical scoping would turn on ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def registerGiven(candidate: BoundGiven): unit = { findOverlappingGiven(candidate, givens) match { @@ -4912,7 +4937,7 @@ class Binder( */ def evidenceTypes(typ: Type): List[Type] = { enclosingEnumType(typ) match { - case Option.None => ListModule.one(typ) + case Option.None => ListModule.one(typ) case Option.Some(enumTyp) => List.Cons(typ, ListModule.one(enumTyp)) } } @@ -4934,10 +4959,10 @@ class Binder( * * `enclosingEnumType` answers with the enum as declared, which is enough for * the operator paths: they compare it against a ground receiver and never - * instantiate it. A goal has to keep the arguments — - * `Eq[List.Cons]` widens to `Eq[List]`, not to `Eq[List]` — and a - * case's type parameters are the enum's, in order, because `bindEnumCases` - * passes them straight through. + * instantiate it. A goal has to keep the arguments — `Eq[List.Cons]` + * widens to `Eq[List]`, not to `Eq[List]` — and a case's type + * parameters are the enum's, in order, because `bindEnumCases` passes them + * straight through. */ def widenedEnumType(typ: Type): Option[Type] = { val args = typ match { @@ -5016,7 +5041,13 @@ class Binder( ) => if (args.length == 1) { Option.Some( - Type.Class(loc, ns, traitName, ListModule.one(operandType), symbol) + Type.Class( + loc, + ns, + traitName, + ListModule.one(operandType), + symbol + ) ) } else Option.None case _ => Option.None @@ -5028,16 +5059,16 @@ class Binder( * proves it. * * The ground half of operator resolution: where `findEvidenceMember` finds - * evidence held by an enclosing declaration, this finds the given itself. - * A given is a singleton whose members are static, so the caller emits an + * evidence held by an enclosing declaration, this finds the given itself. A + * given is a singleton whose members are static, so the caller emits an * ordinary call rather than dispatching through the record — the record * exists to defer a choice, and here there is nothing left to defer. * * The record still comes back, because the member takes one as its trailing - * argument whether the caller needed it to choose or not - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). Resolving is what interns it: a ground call site is a use, - * and a goal nothing uses gets no record. + * argument whether the caller needed it to choose or not ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). Resolving is what interns it: a ground call site is a use, and a goal + * nothing uses gets no record. */ def findGivenMember( rawGoal: Type, @@ -5078,8 +5109,8 @@ class Binder( * holds — this answers for a type the givens name directly, so * `value.show()` works on a `Point` and not only inside `[T: Show]`. * - * Only reached once an ordinary lookup has failed, which is what settles - * the shadowing question: a member a type declares itself always wins. + * Only reached once an ordinary lookup has failed, which is what settles the + * shadowing question: a member a type declares itself always wins. */ def findGivenExtension( leftType: Type, @@ -5093,10 +5124,10 @@ class Binder( * trait applied to `leftType`. * * Matching the head structurally would miss every conditional given, whose - * head holds a type variable: `Show[Box[$0]]` does not equal `Show[Box]` - * and only unification relates them. Going through `findGivenMember` also - * means one place decides which given wins, and one place interns the - * record. + * head holds a type variable: `Show[Box[$0]]` does not equal + * `Show[Box]` and only unification relates them. Going through + * `findGivenMember` also means one place decides which given wins, and one + * place interns the record. */ def scanGivenExtensions( leftType: Type, @@ -5184,8 +5215,8 @@ class Binder( * `K`. Applying the trait to the variable rather than recording the pair * separately is what lets `Types.substitute` do the work later: substituting * `int` for `$0` turns the constraint into `Eq[int]`, which is exactly the - * goal evidence resolution has to satisfy - * ([ADR 0005](../../../docs/architecture/adr/0005-evidence-representation.md), + * goal evidence resolution has to satisfy ([ADR + * 0005](../../../docs/architecture/adr/0005-evidence-representation.md), * decision E). * * Run this after `bindGenericTypeParameters`, which is what defines the @@ -5212,7 +5243,7 @@ class Binder( case Option.None => rest case Option.Some(GenericBoundsSyntax(_, name)) => bindContextBound(name, identifier.location, index, scope) match { - case Option.None => rest + case Option.None => rest case Option.Some(constraint) => List.Cons(constraint, rest) } } @@ -5367,11 +5398,10 @@ class Binder( // Register this object for static constructor creation if it has initialization statements or fields if (allStatements.length > 0 || members.fields.length > 0) { - ctorsToBind = - ctorsToBind.put( - symbol, - ConstructorParams(List.Nil, List.Nil, List.Nil) - ) + ctorsToBind = ctorsToBind.put( + symbol, + ConstructorParams(List.Nil, List.Nil, List.Nil) + ) } } } diff --git a/pnc/src/BoundAssemblyPrinter.pn b/pnc/src/BoundAssemblyPrinter.pn index 45428a0..767a51f 100644 --- a/pnc/src/BoundAssemblyPrinter.pn +++ b/pnc/src/BoundAssemblyPrinter.pn @@ -73,21 +73,21 @@ class BoundAssemblyPrinter( case expr: BoundExpression.EvidenceCall => printEvidenceCall(expr) case expr: BoundExpression.EvidenceRecord => printEvidenceRecord(expr) - case expr: BoundExpression.Cast => printCastExpression(expr) - case expr: BoundExpression.Character => printCharacterLiteral(expr) - case expr: BoundExpression.For => printForExpression(expr) - case expr: BoundExpression.If => printIfExpression(expr) - case expr: BoundExpression.Index => printIndexExpression(expr) - case expr: BoundExpression.Int => printIntLiteral(expr) - case expr: BoundExpression.Is => printIsExpression(expr) - case expr: BoundExpression.MemberAccess => printMemberAccess(expr) - case expr: BoundExpression.New => printNewExpression(expr) - case expr: BoundExpression.String => printStringLiteral(expr) - case expr: BoundExpression.Unary => printUnaryExpression(expr) - case expr: BoundExpression.Unit => printUnitExpression(expr) - case expr: BoundExpression.Variable => printVariable(expr) - case expr: BoundExpression.While => printWhileExpression(expr) - case expr: BoundExpression.Match => printMatchExpression(expr) + case expr: BoundExpression.Cast => printCastExpression(expr) + case expr: BoundExpression.Character => printCharacterLiteral(expr) + case expr: BoundExpression.For => printForExpression(expr) + case expr: BoundExpression.If => printIfExpression(expr) + case expr: BoundExpression.Index => printIndexExpression(expr) + case expr: BoundExpression.Int => printIntLiteral(expr) + case expr: BoundExpression.Is => printIsExpression(expr) + case expr: BoundExpression.MemberAccess => printMemberAccess(expr) + case expr: BoundExpression.New => printNewExpression(expr) + case expr: BoundExpression.String => printStringLiteral(expr) + case expr: BoundExpression.Unary => printUnaryExpression(expr) + case expr: BoundExpression.Unit => printUnitExpression(expr) + case expr: BoundExpression.Variable => printVariable(expr) + case expr: BoundExpression.While => printWhileExpression(expr) + case expr: BoundExpression.Match => printMatchExpression(expr) } } @@ -181,6 +181,7 @@ class BoundAssemblyPrinter( printExpressions(expr.arguments) writeWithColor(ColorPalette.Punctuation, ")") } + /** Printed as `$ev$K$Eq.equals(a, b)` so the evidence the call dispatches * through is visible, unlike an ordinary call where the target is the name. */ diff --git a/pnc/src/BoundNodes.pn b/pnc/src/BoundNodes.pn index f125584..6f63e46 100644 --- a/pnc/src/BoundNodes.pn +++ b/pnc/src/BoundNodes.pn @@ -70,6 +70,7 @@ class BoundParameter(symbol: Symbol, typ: Type) [derive(Eq, Show)] enum BoundPattern { case Literal(literal: BoundLiteral) case Variable(symbol: Symbol) + /** `case Color.Red =>` — a case named without destructuring it. It binds * nothing, but it is a test, which is why it cannot be a `Discard`. * @@ -77,6 +78,7 @@ class BoundParameter(symbol: Symbol, typ: Type) * name everywhere this enum is matched on. */ case TypeTest(typ: Type) + /** `case x: int =>` — a test on the annotation, and then whatever the inner * pattern does. Without the test the annotation would be a claim the match * never checks, and `case x: int` would catch everything. @@ -118,6 +120,7 @@ class BoundMatchCase( ) case Block(statements: List[BoundStatement], expression: BoundExpression) case Boolean(location: TextLocation, value: bool) + /** A trait member called through evidence. * * Distinct from `Call` because the dispatch target is not a token in the @@ -133,13 +136,14 @@ class BoundMatchCase( arguments: List[BoundExpression], resultType: Type ) + /** The static field holding the evidence record that proves a goal. * - * Every call to a given's member carries one as its trailing argument - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). Distinct from a member access because there is no receiver to - * name: the record lives on the program object and the binder holds the - * field directly. + * Every call to a given's member carries one as its trailing argument ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). Distinct from a member access because there is no receiver to name: + * the record lives on the program object and the binder holds the field + * directly. */ case EvidenceRecord(location: TextLocation, field: Symbol, resultType: Type) case Call( diff --git a/pnc/src/Builtin.pn b/pnc/src/Builtin.pn index 4877bd1..96a86ed 100644 --- a/pnc/src/Builtin.pn +++ b/pnc/src/Builtin.pn @@ -66,27 +66,27 @@ object Builtin { /** The id for a method's qualified name, or `None` if it names no builtin. */ def idOf(qualifiedName: string): int = { qualifiedName match { - case "println" => Println - case "print" => Print - case "panic" => Panic - case "exit" => Exit - case "assert" => Assert - case "mod" => Mod - case "string.apply" => StringApply - case "int.apply" => IntApply - case "bool.apply" => BoolApply - case "char.apply" => CharApply - case "string.substring" => Substring - case "string.endsWith" => EndsWith - case "string.compareTo" => StringCompareTo - case "int.compareTo" => IntCompareTo - case "File.readAllText" => ReadAllText - case "File.readAllBytes" => ReadAllBytes - case "File.writeAllBytes" => WriteAllBytes - case "File.writeAllText" => WriteAllText - case "Path.combine" => PathCombine - case "Path.nameWithoutExtension" => PathName - case _ => None + case "println" => Println + case "print" => Print + case "panic" => Panic + case "exit" => Exit + case "assert" => Assert + case "mod" => Mod + case "string.apply" => StringApply + case "int.apply" => IntApply + case "bool.apply" => BoolApply + case "char.apply" => CharApply + case "string.substring" => Substring + case "string.endsWith" => EndsWith + case "string.compareTo" => StringCompareTo + case "int.compareTo" => IntCompareTo + case "File.readAllText" => ReadAllText + case "File.readAllBytes" => ReadAllBytes + case "File.writeAllBytes" => WriteAllBytes + case "File.writeAllText" => WriteAllText + case "Path.combine" => PathCombine + case "Path.nameWithoutExtension" => PathName + case _ => None } } diff --git a/pnc/src/CompilerSettings.pn b/pnc/src/CompilerSettings.pn index cb4f73e..258f0a1 100644 --- a/pnc/src/CompilerSettings.pn +++ b/pnc/src/CompilerSettings.pn @@ -25,8 +25,8 @@ class CompilerSettings( printBoundAssembly: bool, printLoweredAssembly: bool, transpile: bool, - /** Compile and execute in one step, instead of emitting. There is no - * output file in this mode — every positional argument is a source. + /** Compile and execute in one step, instead of emitting. There is no output + * file in this mode — every positional argument is a source. */ run: bool ) diff --git a/pnc/src/DiagnosticBag.pn b/pnc/src/DiagnosticBag.pn index c5e59fa..0b58409 100644 --- a/pnc/src/DiagnosticBag.pn +++ b/pnc/src/DiagnosticBag.pn @@ -250,16 +250,16 @@ class DiagnosticBag(settings: CompilerSettings) { /** `operator ~(…)`. Only a token the language already parses as a binary * operator may be declared — new syntax comes from a language change, not - * from a library - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * from a library ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ /** `[trace(…)]`. `derive` is the only attribute the language has. */ def reportUnknownAttribute(location: TextLocation, name: string): unit = report(location, name + " is not an attribute") /** `[derive(Eq)] def f() = 1`. Derivation is over constructor parameters, so - * only a class or an enum has anything to derive - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * only a class or an enum has anything to derive ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def reportDeriveNotSupported(location: TextLocation, what: string): unit = report(location, "derive cannot be applied to " + what) @@ -274,9 +274,9 @@ class DiagnosticBag(settings: CompilerSettings) { name + " cannot be derived; only Eq, Ord and Show can" ) - /** A generic type's derived given is conditional — `Eq[Box[T]]` given - * `Eq[T]` — and a conditional given cannot reach its own premise yet - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + /** A generic type's derived given is conditional — `Eq[Box[T]]` given `Eq[T]` + * — and a conditional given cannot reach its own premise yet ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def reportDeriveOnGenericType(location: TextLocation, name: string): unit = report(location, "Cannot derive for " + name + ": it has type parameters") @@ -303,8 +303,8 @@ class DiagnosticBag(settings: CompilerSettings) { /** A token belongs to one trait. Without that rule `a == b` would need * overload resolution across traits, and the point of the design is that a - * use site resolves to one piece of evidence - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * use site resolves to one piece of evidence ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def reportOperatorAlreadyClaimed( location: TextLocation, diff --git a/pnc/src/Dictionary.pn b/pnc/src/Dictionary.pn index 28b82ab..a06046f 100644 --- a/pnc/src/Dictionary.pn +++ b/pnc/src/Dictionary.pn @@ -68,7 +68,7 @@ class Dictionary[K, V](list: List[KeyValue[K, V]]) { while (!rest.isEmpty) { rest match { - case List.Nil => rest = List.Nil + case List.Nil => rest = List.Nil case List.Cons(kv, next) => // guarded so only the first match goes, matching the recursive // version this replaced diff --git a/pnc/src/Emitter.pn b/pnc/src/Emitter.pn index 920391a..36e8beb 100644 --- a/pnc/src/Emitter.pn +++ b/pnc/src/Emitter.pn @@ -215,7 +215,7 @@ class Emitter( map: Dictionary[Symbol, int] ): Dictionary[Symbol, int] = { symbols match { - case List.Nil => map + case List.Nil => map case List.Cons(head, tail) => // Evidence takes an argument slot like a declared parameter; it is a // separate kind only so printers and arity checks can tell them apart. @@ -288,7 +288,7 @@ class Emitter( def emitMethod(symbol: Symbol, context: EmitContext): bool = { assembly.functionBodies.get(symbol) match { - case Option.None => false + case Option.None => false case Option.Some(value) => // Evidence records first: they are method tokens, so this is the // earliest point they can be built, and everything that reads one runs @@ -384,8 +384,7 @@ class Emitter( * method tokens, laid out in the trait's declaration order so the reading * side can index it without knowing which given it came from. */ - /** Builds each parameterless enum case once and parks it in its static - * field. + /** Builds each parameterless enum case once and parks it in its static field. * * `Color.Red` names a value rather than making one, so every mention has to * be the same object — otherwise reference identity, which is what `==` @@ -436,8 +435,9 @@ class Emitter( * The two passes are what make a cycle work rather than an optimisation: * `Eq[Symbol]` points at `Eq[List[Symbol]]`, which points back. Filling as * it goes would need one of them to load a field that has not been stored - * yet ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision E). + * yet ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * E). */ def emitEvidenceRecords( records: List[BoundEvidenceRecord], @@ -507,7 +507,7 @@ class Emitter( def evidenceTraitMembers(candidate: BoundGiven): List[Symbol] = { binder.getTypeSymbol(candidate.head) match { - case Option.None => List.Nil + case Option.None => List.Nil case Option.Some(traitSymbol) => binder.traitMembers(traitSymbol) } } @@ -849,9 +849,9 @@ class Emitter( * `Calli` dispatches on the token that comes back. * * The record is loaded twice — once as the member's own trailing argument, - * once to read the token out of - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C). The first is what a conditional given reads its premise from. + * once to read the token out of ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C). The first is what a conditional given reads its premise from. */ def emitEvidenceCall( expr: LoweredExpression.EvidenceCall, @@ -895,9 +895,9 @@ class Emitter( /** Evidence reaches a method as its own parameter, as a field on the receiver * in an instance method of a constrained class, or — for a conditional given * reading its own premise — out of the dependency half of the record it was - * reached through - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision D). + * reached through ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * D). */ def emitEvidenceValue( evidence: BoundEvidence, @@ -1015,16 +1015,17 @@ class Emitter( */ def isCharExpression(expr: LoweredExpression): bool = { expr match { - case _: LoweredExpression.Character => true - case value: LoweredExpression.ArrayAccess => isCharType(value.resultType) - case value: LoweredExpression.BinaryExpression => isCharType(value.resultType) - case value: LoweredExpression.Cast => isCharType(value.resultType) - case value: LoweredExpression.Call => isCharType(value.resultType) - case value: LoweredExpression.EvidenceCall => isCharType(value.resultType) - case value: LoweredExpression.Unary => isCharType(value.resultType) - case value: LoweredExpression.Variable => isCharSymbol(value.symbol) - case value: LoweredExpression.MemberAccess => isCharSymbol(value.symbol) - case _ => false + case _: LoweredExpression.Character => true + case value: LoweredExpression.ArrayAccess => isCharType(value.resultType) + case value: LoweredExpression.BinaryExpression => + isCharType(value.resultType) + case value: LoweredExpression.Cast => isCharType(value.resultType) + case value: LoweredExpression.Call => isCharType(value.resultType) + case value: LoweredExpression.EvidenceCall => isCharType(value.resultType) + case value: LoweredExpression.Unary => isCharType(value.resultType) + case value: LoweredExpression.Variable => isCharSymbol(value.symbol) + case value: LoweredExpression.MemberAccess => isCharSymbol(value.symbol) + case _ => false } } @@ -1332,7 +1333,10 @@ class Emitter( expr: LoweredExpression.Variable, context: EmitContext ): unit = - emitLoadArgument(context.getParamIndex(expr.symbol), expr.location.startLine) + emitLoadArgument( + context.getParamIndex(expr.symbol), + expr.location.startLine + ) def emitLoadArgument(index: int, line: int): unit = { if (index < 4) { diff --git a/pnc/src/ExprBinder.pn b/pnc/src/ExprBinder.pn index 71353cd..692cffb 100644 --- a/pnc/src/ExprBinder.pn +++ b/pnc/src/ExprBinder.pn @@ -987,7 +987,10 @@ class ExprBinder( /** Whether the right operand widens to the operator member's second * parameter. */ - def operandFits(right: BoundExpression, parameters: List[BoundParameter]): bool = { + def operandFits( + right: BoundExpression, + parameters: List[BoundParameter] + ): bool = { parameters match { case List.Cons(_, List.Cons(second, _)) => conversionClassifier.widensTo(binder.getType(right), second.typ) @@ -999,10 +1002,9 @@ class ExprBinder( * * `evidence` decides the node: `Some` for a record the caller has to load, * `None` for a static call on the given itself. `record` is the static field - * that call has to pass on as the member's trailing argument - * ([ADR 0006](../../../docs/architecture/adr/0006-conditional-givens.md), - * decision C); the `EvidenceCall` shape loads its own, so the two are never - * both set. + * that call has to pass on as the member's trailing argument ([ADR + * 0006](../../../docs/architecture/adr/0006-conditional-givens.md), decision + * C); the `EvidenceCall` shape loads its own, so the two are never both set. */ def bindOperatorCall( location: TextLocation, @@ -1801,7 +1803,9 @@ class ExprBinder( args, scope ) - case Option.Some(Type.GenericFunction(loc, generics, traits, params, _)) => + case Option.Some( + Type.GenericFunction(loc, generics, traits, params, _) + ) => val typeArgs = if (!explicitTypeArgs.isEmpty) explicitTypeArgs else { diff --git a/pnc/src/Lowered.pn b/pnc/src/Lowered.pn index 00a828b..409318f 100644 --- a/pnc/src/Lowered.pn +++ b/pnc/src/Lowered.pn @@ -130,6 +130,7 @@ class LoweredLeftHandSideBlock( arguments: Chain[LoweredExpression], resultType: Type ) + /** A trait member called through evidence. The emitter loads the evidence, * loads the member's token from it, and issues `Calli`; `arguments` already * has the receiver prepended, because a trait declares both operands as @@ -142,6 +143,7 @@ class LoweredLeftHandSideBlock( arguments: Chain[LoweredExpression], resultType: Type ) + /** The static field holding an evidence record, loaded as the trailing * argument of a call to a given's member (ADR 0006, decision C). */ @@ -619,7 +621,10 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { ) case List.Cons(head, tail) => val block = - lowerExpression(head, LoweredBlock(statements, LoweredExpression.Unit)) + lowerExpression( + head, + LoweredBlock(statements, LoweredExpression.Unit) + ) lowerEvidenceCallArguments( call, tail, @@ -1291,9 +1296,9 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { /** One case, as `if () { ; } else `. * - * An irrefutable pattern — `case _` or `case x` — has no test, so it - * becomes the body directly and whatever follows it is unreachable, which - * is what a catch-all means. + * An irrefutable pattern — `case _` or `case x` — has no test, so it becomes + * the body directly and whatever follows it is unreachable, which is what a + * catch-all means. */ def boundMatchCaseToExpression( variable: Symbol, @@ -1304,7 +1309,8 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { val scrutinee: BoundExpression = BoundExpression.Variable(matchCase.location, variable, Option.None) - val bindings = patternBindings(scrutinee, matchCase.pattern, matchCase.location) + val bindings = + patternBindings(scrutinee, matchCase.pattern, matchCase.location) val body: BoundExpression = if (bindings.isEmpty) matchCase.result else BoundExpression.Block(bindings, matchCase.result) @@ -1355,7 +1361,7 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { val test = BoundExpression.Is(location, scrutinee, typ) patternTest(scrutinee, inner, location) match { - case Option.None => Option.Some(test) + case Option.None => Option.Some(test) case Option.Some(innerTest) => // nested, not `&&`-ed: the inner pattern may read the value as the // annotated type, which only the outer test establishes @@ -1413,7 +1419,8 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { fields match { case List.Nil => BoundExpression.Boolean(location, true) case List.Cons(field, tail) => - val rest = subPatternTests(scrutinee, tail, patterns, index + 1, location) + val rest = + subPatternTests(scrutinee, tail, patterns, index + 1, location) if (index >= patterns.length) rest else @@ -1516,13 +1523,13 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { */ def constructorCaseType(constructor: Symbol): Option[Type] = { constructor.parent match { - case Option.None => Option.None + case Option.None => Option.None case Option.Some(owner) => binder.tryGetSymbolType(owner) } } - /** The fields a constructor pattern destructures, in the order its - * parameters are declared. + /** The fields a constructor pattern destructures, in the order its parameters + * are declared. * * Taken from the constructor's parameters rather than from the type's * fields, because a pattern is positional and `members()` gives a class's @@ -1567,8 +1574,8 @@ class ExpressionLowerer(symbol: Symbol, binder: Binder) { binder.getSymbolType(field) ) - /** A scrutinee as something a member access can hang off. Only the two - * shapes `patternTest` builds ever reach this. + /** A scrutinee as something a member access can hang off. Only the two shapes + * `patternTest` builds ever reach this. */ def asLeftHandSide(expr: BoundExpression): BoundLeftHandSide = { expr match { diff --git a/pnc/src/LoweredAssemblyPrinter.pn b/pnc/src/LoweredAssemblyPrinter.pn index 25f1028..f938535 100644 --- a/pnc/src/LoweredAssemblyPrinter.pn +++ b/pnc/src/LoweredAssemblyPrinter.pn @@ -307,8 +307,8 @@ class LoweredAssemblyPrinter( ast.writeWithColor(ColorPalette.String, "'" + string(expr.value) + "'") } - /** `$ev$K$Eq.equals(a, b)` — the evidence is shown because it is the - * dispatch target, not a receiver. + /** `$ev$K$Eq.equals(a, b)` — the evidence is shown because it is the dispatch + * target, not a receiver. */ def printEvidenceCall(call: LoweredExpression.EvidenceCall): unit = { ast.append(evidenceName(call.evidence)) diff --git a/pnc/src/Metadata.pn b/pnc/src/Metadata.pn index 8bd36cc..1c70e75 100644 --- a/pnc/src/Metadata.pn +++ b/pnc/src/Metadata.pn @@ -275,8 +275,8 @@ class Metadata() { /** Every table, in an order `read` repeats. * * Strings were left out, which is why nothing could be read back: every - * other table refers to one by token, so an image without them has names - * for nothing and `Ldstr` has no literal to load. + * other table refers to one by token, so an image without them has names for + * nothing and `Ldstr` has no literal to load. */ def write(buffer: IntList): unit = { typeDefs.write(buffer) diff --git a/pnc/src/Opcode.pn b/pnc/src/Opcode.pn index a0d01aa..5aece27 100644 --- a/pnc/src/Opcode.pn +++ b/pnc/src/Opcode.pn @@ -63,9 +63,9 @@ object Opcode { /** Call a builtin, whose id is the operand. * - * A builtin is an `extern` method with no body to call into. One - * instruction rather than one per builtin: the id says which, so declaring - * a builtin does not grow the instruction set. See `Builtin`. + * A builtin is an `extern` method with no body to call into. One instruction + * rather than one per builtin: the id says which, so declaring a builtin + * does not grow the instruction set. See `Builtin`. */ val Callx = 62 diff --git a/pnc/src/Parser.pn b/pnc/src/Parser.pn index ae1992d..9d2a6f3 100644 --- a/pnc/src/Parser.pn +++ b/pnc/src/Parser.pn @@ -483,8 +483,8 @@ class Parser( /** A context bound: the `Eq` of `[K: Eq]`, meaning the declaration requires * evidence satisfying `Eq[K]`. One bound per parameter — a parameter needing - * two capabilities is not expressible yet - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * two capabilities is not expressible yet ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def parseGenericBounds(): Option[GenericBoundsSyntax] = { debugPrint("parseGenericBounds") @@ -498,9 +498,9 @@ class Parser( /** `[derive(Eq, Ord, Show)]`, when the member starts with one. * - * Unambiguous at member position: no expression in the language starts - * with `[` — generic arguments and indexing are both postfix — so a - * bracket here can only open an attribute. + * Unambiguous at member position: no expression in the language starts with + * `[` — generic arguments and indexing are both postfix — so a bracket here + * can only open an attribute. */ def parseDeriveAttribute(): Option[DeriveAttributeSyntax] = { if (currentKind() != SyntaxKind.OpenBracketToken) Option.None @@ -1307,9 +1307,9 @@ class Parser( * `operator` is a contextual keyword, not a reserved one. It cannot be * reserved: the compiler's own sources use `operator` as an identifier 71 * times — `BinaryOperator.operator`, `node.operator` — and `pncs` has to - * compile its own transpiled twin. Three tokens settle it without - * ambiguity, because no member or statement position in those sources - * begins with `operator` followed by an operator token. + * compile its own transpiled twin. Three tokens settle it without ambiguity, + * because no member or statement position in those sources begins with + * `operator` followed by an operator token. */ def isOperatorDeclaration(): bool = current().kind == SyntaxKind.IdentifierToken && @@ -1320,10 +1320,10 @@ class Parser( /** `operator ==(a: T, b: T): bool` inside a trait or a given. * * The result is an ordinary `FunctionDeclarationSyntax` whose name is the - * operator's own text, so the member binds, types and emits like any other - * — what makes it an operator is which token a trait claims, not a - * different kind of declaration - * ([ADR 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). + * operator's own text, so the member binds, types and emits like any other — + * what makes it an operator is which token a trait claims, not a different + * kind of declaration ([ADR + * 0004](../../../docs/architecture/adr/0004-traits-given-evidence-and-contextual-extensions.md)). */ def parseOperatorDeclaration(): MemberSyntax = { debugPrint("parseOperatorDeclaration") diff --git a/pnc/src/Program.pn b/pnc/src/Program.pn index 5eed5d9..2f498c3 100644 --- a/pnc/src/Program.pn +++ b/pnc/src/Program.pn @@ -127,15 +127,14 @@ object Program { } } - /** Runs a clean compilation and answers the code the process should end - * with. + /** Runs a clean compilation and answers the code the process should end with. * * A program that chose its own code reports that code; one that failed at * runtime reports 1, there being no code to honour. */ def execute(compilation: Compilation): int = { compilation.exec() match { - case InterpretResult.Exit(code) => code + case InterpretResult.Exit(code) => code case InterpretResult.RuntimeError => 1 case InterpretResult.CompileError => 1 // `Ok` and `OkValue` are both a program that ran to the end. What it diff --git a/pnc/src/SymbolKind.pn b/pnc/src/SymbolKind.pn index e67c922..8af86fa 100644 --- a/pnc/src/SymbolKind.pn +++ b/pnc/src/SymbolKind.pn @@ -17,9 +17,9 @@ /** A synthesized parameter carrying the evidence for one context bound. * * Its own kind rather than `Parameter` so printers and arity diagnostics can - * tell it from something the user wrote, while the emitter still allots it an - * argument slot — the mirror of the `This` problem below, which needed to be - * skipped rather than counted. + * tell it from something the user wrote, while the emitter still allots it + * an argument slot — the mirror of the `This` problem below, which needed to + * be skipped rather than counted. */ case Evidence case Alias diff --git a/pnc/src/SyntaxFacts.pn b/pnc/src/SyntaxFacts.pn index 58a1d02..7c1db3b 100644 --- a/pnc/src/SyntaxFacts.pn +++ b/pnc/src/SyntaxFacts.pn @@ -134,11 +134,11 @@ object SyntaxFacts { def isKeywordKind(kind: int): bool = kind >= SyntaxKind.FirstKeyword && kind <= SyntaxKind.LastKeyword - /** Every token in the operator block, which is wider than - * `isBinaryOperator`: `=`, `:`, `.` and `~` are operator tokens that no - * binary expression uses. The parser needs the wider set to recognise - * `operator ~(…)` as an operator declaration at all, so that it can report - * the token as undeclarable rather than fail on a stray member. + /** Every token in the operator block, which is wider than `isBinaryOperator`: + * `=`, `:`, `.` and `~` are operator tokens that no binary expression uses. + * The parser needs the wider set to recognise `operator ~(…)` as an operator + * declaration at all, so that it can report the token as undeclarable rather + * than fail on a stray member. */ def isOperatorKind(kind: int): bool = kind >= SyntaxKind.AmpersandAmpersandToken && diff --git a/pnc/src/TypeInference.pn b/pnc/src/TypeInference.pn index 6ee1a9b..aadbf0e 100644 --- a/pnc/src/TypeInference.pn +++ b/pnc/src/TypeInference.pn @@ -72,7 +72,8 @@ class TypeInference(binder: Binder) { // it. Only a result with structure is evidence. Option.None case _ => - val typeMap = inferTypeFromPair(resultType, expectedType, emptyTypeMap()) + val typeMap = + inferTypeFromPair(resultType, expectedType, emptyTypeMap()) if (allSolved(genericParams, typeMap, 0)) { Option.Some(mapGenericParamsToTypes(genericParams, typeMap)) } else { diff --git a/pnc/src/VM.pn b/pnc/src/VM.pn index 321d3c7..b397ff0 100644 --- a/pnc/src/VM.pn +++ b/pnc/src/VM.pn @@ -10,9 +10,9 @@ using system.io.Path ) // completed running the program and returned a value /** The program called `exit(code)`. * - * Distinct from `OkValue`, which carries the value the program evaluated - * to: `exit(3)` and a program whose last expression is `3` mean different - * things to whatever launched it, and only the first one chose its code. + * Distinct from `OkValue`, which carries the value the program evaluated to: + * `exit(3)` and a program whose last expression is `3` mean different things + * to whatever launched it, and only the first one chose its code. */ case Exit(code: int) case CompileError @@ -335,13 +335,13 @@ class VM( condition match { case Value.Bool(true) => push(Value.Uninitialized) case Value.Bool(false) => runtimeError(valueToString(message)) - case _ => runtimeError("Expected bool condition for assert") + case _ => runtimeError("Expected bool condition for assert") } } /** `string(value)`. */ def stringApplyOp(): InterpretResult = { - push(Value.String(valueToString(pop()))) + push(Value.String(valueToString(pop()))) } /** `string(c)` where `c` is a char — the character itself, not its code. @@ -361,74 +361,74 @@ class VM( /** `bool(value)`. */ def boolApplyOp(): InterpretResult = { - val a = pop() - a match { - case Value.Int(0) => - pushBool(false) - InterpretResult.Continue - case Value.Int(_) => - pushBool(true) - InterpretResult.Continue - case Value.Bool(b) => - pushBool(b) - InterpretResult.Continue - case _ => - runtimeError("Cannot convert value to bool: " + string(a)) - } + val a = pop() + a match { + case Value.Int(0) => + pushBool(false) + InterpretResult.Continue + case Value.Int(_) => + pushBool(true) + InterpretResult.Continue + case Value.Bool(b) => + pushBool(b) + InterpretResult.Continue + case _ => + runtimeError("Cannot convert value to bool: " + string(a)) + } } /** `int(value)`. */ def intApplyOp(): InterpretResult = { - val a = pop() - a match { - case Value.Int(i) => - push(Value.Int(i)) - InterpretResult.Continue - case Value.Bool(true) => - push(Value.Int(1)) - InterpretResult.Continue - case Value.Bool(false) => - push(Value.Int(0)) - InterpretResult.Continue - case Value.String(s) => - if (s.length == 0) { - runtimeError("Cannot convert empty string to int") - } else if (s(0) == '-') { - atoi(s, 1, 0) match { - case Option.None => runtimeError("Cannot convert string to int") - case Option.Some(value) => push(Value.Int(-value)) - } - } else { - atoi(s, 0, 0) match { - case Option.None => runtimeError("Cannot convert string to int") - case Option.Some(value) => push(Value.Int(value)) - } + val a = pop() + a match { + case Value.Int(i) => + push(Value.Int(i)) + InterpretResult.Continue + case Value.Bool(true) => + push(Value.Int(1)) + InterpretResult.Continue + case Value.Bool(false) => + push(Value.Int(0)) + InterpretResult.Continue + case Value.String(s) => + if (s.length == 0) { + runtimeError("Cannot convert empty string to int") + } else if (s(0) == '-') { + atoi(s, 1, 0) match { + case Option.None => runtimeError("Cannot convert string to int") + case Option.Some(value) => push(Value.Int(-value)) } + } else { + atoi(s, 0, 0) match { + case Option.None => runtimeError("Cannot convert string to int") + case Option.Some(value) => push(Value.Int(value)) + } + } - case _ => - runtimeError("Cannot convert value to int") - } + case _ => + runtimeError("Cannot convert value to int") + } } /** `char(value)`. */ def charApplyOp(): InterpretResult = { - val a = pop() - a match { - case Value.Int(i) => - push(Value.Int(i)) + val a = pop() + a match { + case Value.Int(i) => + push(Value.Int(i)) + InterpretResult.Continue + case Value.String(s) => + if (s.length == 1) { + push(Value.Int(s(0))) InterpretResult.Continue - case Value.String(s) => - if (s.length == 1) { - push(Value.Int(s(0))) - InterpretResult.Continue - } else { - runtimeError( - "Cannot convert string of length " + string(s.length) + " to char" - ) - } - case _ => - runtimeError("Cannot convert value to char") - } + } else { + runtimeError( + "Cannot convert string of length " + string(s.length) + " to char" + ) + } + case _ => + runtimeError("Cannot convert value to char") + } } /** `compareTo` for every type that has an ordering. diff --git a/pnc/src/compilation.pn b/pnc/src/compilation.pn index d09771c..366fdf8 100644 --- a/pnc/src/compilation.pn +++ b/pnc/src/compilation.pn @@ -73,9 +73,9 @@ class Compilation( /** The printers, as text. * * `withColor` off is what anything that compares the output wants — a - * snapshot of a coloured tree is a snapshot of the escape codes. The - * builder accumulates rather than printing as it goes, which is the other - * half of being able to hand the result back. + * snapshot of a coloured tree is a snapshot of the escape codes. The builder + * accumulates rather than printing as it goes, which is the other half of + * being able to hand the result back. */ def symbolsText(withColor: bool): string = { val sb = IndentedStringBuilder(false)