From 9b125f6a1bd9379d78f88f9f356a0385e817ccb1 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Sat, 24 Feb 2024 13:24:19 +0100 Subject: [PATCH] Allow function calls to partially fill RHS (fixes #52) * post-expr-calls (`a.valueOr: ...`) don't count towards dot stacking * prefer new line for lists etc if full line fits on RHS * simple lhs of dot expressions can partially fill a line --- src/phast.nim | 30 +++++------ src/phoptions.nim | 15 +++--- src/phrenderer.nim | 77 ++++++++++++++++++--------- tests/after/exprs.nim | 18 ++++++- tests/after/exprs.nim.nph.yaml | 93 +++++++++++++++++++++++++++++++++ tests/after/postexprs.nim | 11 ++-- tests/before/exprs.nim | 9 ++++ tests/before/exprs.nim.nph.yaml | 93 +++++++++++++++++++++++++++++++++ 8 files changed, 284 insertions(+), 62 deletions(-) diff --git a/src/phast.nim b/src/phast.nim index 9d056f4..13e494c 100644 --- a/src/phast.nim +++ b/src/phast.nim @@ -672,9 +672,8 @@ type TSymKinds* = set[TSymKind] const - routineKinds* = { - skProc, skFunc, skMethod, skIterator, skConverter, skMacro, skTemplate - } + routineKinds* = + {skProc, skFunc, skMethod, skIterator, skConverter, skMacro, skTemplate} ExportableSymKinds* = {skVar, skLet, skConst, skType, skEnumField, skStub} + routineKinds tfUnion* = tfNoSideEffect @@ -683,9 +682,8 @@ const tfReturnsNew* = tfInheritable skError* = skUnknown -var eqTypeFlags* = { - tfIterator, tfNotNil, tfVarIsPtr, tfGcSafe, tfNoSideEffect, tfIsOutParam, tfSendable -} +var eqTypeFlags* = + {tfIterator, tfNotNil, tfVarIsPtr, tfGcSafe, tfNoSideEffect, tfIsOutParam, tfSendable} ## type flags that are essential for type equality. ## This is now a variable because for emulation of version:1.0 we ## might exclude {tfGcSafe, tfNoSideEffect}. @@ -1353,9 +1351,8 @@ const resultPos* = 7 dispatcherPos* = 8 nfAllFieldsSet* = nfBase2 - nkCallKinds* = { - nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit, nkHiddenCallConv - } + nkCallKinds* = + {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit, nkHiddenCallConv} nkIdentKinds* = {nkIdent, nkSym, nkAccQuoted, nkOpenSymChoice, nkClosedSymChoice} nkPragmaCallKinds* = {nkExprColonExpr, nkCall, nkCallStrLit} nkLiterals* = {nkCharLit .. nkTripleStrLit} @@ -1368,9 +1365,8 @@ const nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice} nkStrKinds* = {nkStrLit .. nkTripleStrLit} skLocalVars* = {skVar, skLet, skForVar, skParam, skResult} - skProcKinds* = { - skProc, skFunc, skTemplate, skMacro, skIterator, skMethod, skConverter - } + skProcKinds* = + {skProc, skFunc, skTemplate, skMacro, skIterator, skMethod, skConverter} defaultSize = -1 defaultAlignment = -1 defaultOffset* = -1 @@ -1849,9 +1845,8 @@ proc newProcNode*( result = newNodeI(kind, info) result.sons = @[name, pattern, genericParams, params, pragmas, exceptions, body] -const AttachedOpToStr*: array[TTypeAttachedOp, string] = [ - "=wasMoved", "=destroy", "=copy", "=dup", "=sink", "=trace", "=deepcopy" -] +const AttachedOpToStr*: array[TTypeAttachedOp, string] = + ["=wasMoved", "=destroy", "=copy", "=dup", "=sink", "=trace", "=deepcopy"] proc `$`*(s: PSym): string = if s != nil: @@ -2444,9 +2439,8 @@ proc addParam*(procType: PType, param: PSym) = rawAddSon(procType, param.typ) -const magicsThatCanRaise = { - mNone, mSlurp, mStaticExec, mParseExprToAst, mParseStmtToAst, mEcho -} +const magicsThatCanRaise = + {mNone, mSlurp, mStaticExec, mParseExprToAst, mParseStmtToAst, mEcho} proc canRaiseConservative*(fn: PNode): bool = if fn.kind == nkSym and fn.sym.magic notin magicsThatCanRaise: diff --git a/src/phoptions.nim b/src/phoptions.nim index 76bd1f0..1e61ad6 100644 --- a/src/phoptions.nim +++ b/src/phoptions.nim @@ -197,12 +197,10 @@ type # old unused: cmdInterpret, cmdDef: def feature (find definition for IDEs) const - cmdBackends* = { - cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToJS, cmdCrun - } - cmdDocLike* = { - cmdDoc0, cmdDoc, cmdDoc2tex, cmdJsondoc0, cmdJsondoc, cmdCtags, cmdBuildindex - } + cmdBackends* = + {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToJS, cmdCrun} + cmdDocLike* = + {cmdDoc0, cmdDoc, cmdDoc2tex, cmdJsondoc0, cmdJsondoc, cmdCtags, cmdBuildindex} type NimVer* = tuple[major: int, minor: int, patch: int] @@ -602,9 +600,8 @@ template newPackageCache*(): untyped = proc newProfileData(): ProfileData = ProfileData(data: newTable[TLineInfo, ProfileInfo]()) -const foreignPackageNotesDefault* = { - hintProcessing, warnUnknownMagic, hintQuitCalled, hintExecuting, hintUser, warnUser -} +const foreignPackageNotesDefault* = + {hintProcessing, warnUnknownMagic, hintQuitCalled, hintExecuting, hintUser, warnUser} proc isDefined*(conf: ConfigRef, symbol: string): bool diff --git a/src/phrenderer.nim b/src/phrenderer.nim index edc4574..a29c471 100644 --- a/src/phrenderer.nim +++ b/src/phrenderer.nim @@ -394,11 +394,18 @@ proc hasIndent(n: PNode): bool = nkObjectTy, nkEnumTy, nkBlockStmt, nkBlockExpr } +const postExprBlocks = { + nkStmtList, nkStmtListExpr, nkOfBranch, nkElifBranch, nkElse, nkExceptBranch, + nkFinally, nkDo +} + proc isStackedCall(n: PNode, inCall: bool): bool = # At least two calls to enable "stacking" mode case n.kind of nkCall: - if inCall: + if n.len > 1 and n.lastSon.kind in postExprBlocks: + isStackedCall(n[0], inCall) + elif inCall: true else: isStackedCall(n[0], true) @@ -671,16 +678,28 @@ proc lstmts(g: var TOutput, n: PNode, flags: SubFlags = {}, doIndent = true): Li withSrcLen(g): gstmts(sl, n, flags, doIndent) -proc nlsub(g: TOutput, n: PNode, flags: SubFlags = {}): LineLen = +proc nlsubImpl(g: TOutput, n: PNode, flags: SubFlags): (bool, LineLen) = ## How many characters until the next early line break - let ll = lsub(g, n, flags) - case n.kind - of nkPar, nkClosure, nkCurly, nkBracket, nkTableConstr, nkStmtListExpr, nkTupleConstr: - (1, ll[1]) - of nkPragma, nkPragmaExpr: - (2, ll[1]) + if n.kind == nkDotExpr: + let (a, l) = nlsubImpl(g, n[0], flags) + if a: + (a, l) + else: + (false, l + lsub(g, n[1]) + 1) else: - ll + let ll = lsub(g, n, flags) + case n.kind + of nkPar, nkClosure, nkCurly, nkBracket, nkTableConstr, nkStmtListExpr, + nkTupleConstr: + (true, (1, ll[1])) + of nkPragma, nkPragmaExpr: + (true, (2, ll[1])) + else: + (false, ll) + +proc nlsub(g: TOutput, n: PNode, flags: SubFlags = {}): LineLen = + ## How many characters until the next early line break + nlsubImpl(g, n, flags)[1] proc fits(g: TSrcLen, x: LineLen): bool = # Line lengths are computed assuming no extra line breaks @@ -1330,6 +1349,15 @@ proc doParamsAux(g: var TOutput, params: PNode) = putWithSpace(g, tkOpr, "->") gsub(g, params[0]) +proc isDotCall(n: PNode): bool = + case n.kind + of nkDotExpr: + isDotCall(n[0]) + of nkCall: + true + else: + false + proc gsubOptNL(g: var TOutput, n: PNode, indentNL = IndentWidth, flags: SubFlags = {}) = # Output n on the same line if it fits, else continue on next - indentation is # always set up in case a comment linebreaks the statement @@ -1344,19 +1372,22 @@ proc gsubOptNL(g: var TOutput, n: PNode, indentNL = IndentWidth, flags: SubFlags const suboptAvoidNL = { nkCall, nkConv, nkPattern, nkObjConstr, nkCast, nkStaticExpr, nkBracketExpr, nkCurlyExpr, nkPragmaExpr, nkCommand, nkExprEqExpr, nkAsgn, nkFastAsgn, nkClosure, - nkTupleConstr, nkCurly, nkArgList, nkTableConstr, nkBracket, nkDotExpr, nkBind, - nkDo, nkIdentDefs, nkConstDef, nkVarTuple, nkExprColonExpr, nkTypeOfExpr, - nkDistinctTy, nkTypeDef, nkBlockStmt, nkBlockExpr, nkLambda, nkProcTy + nkTupleConstr, nkCurly, nkArgList, nkTableConstr, nkBracket, nkBind, nkDo, + nkIdentDefs, nkConstDef, nkVarTuple, nkExprColonExpr, nkTypeOfExpr, nkDistinctTy, + nkTypeDef, nkBlockStmt, nkBlockExpr, nkLambda, nkProcTy } let - sublen = nlsub(g, n, flags = flags) + sublen = lsub(g, n, flags = flags) nl = - overflows(g, sublen) and ( - n.kind notin suboptAvoidNL or fits(g, sublen + g.indent + indentNL) or - isStackedCall(n, false) - ) - ind = condIndent(g, nl or g.pendingNL >= 0 or n.prefix.len > 0, indentNL) + ( + ((n.kind notin suboptAvoidNL and not isDotCall(n))) and + overflows(g, nlsub(g, n, flags = flags)) + ) or (overflows(g, sublen) and fits(g, sublen + g.indent + indentNL)) + + ind = condIndent( + g, isStackedCall(n, false) or nl or g.pendingNL >= 0 or n.prefix.len > 0, indentNL + ) flags = if ind > 0: {sfNoIndent} + flags @@ -1395,11 +1426,6 @@ proc infixArgument(g: var TOutput, n: PNode, i: int, flags: SubFlags) = if needsParenthesis: put(g, tkParRi, ")") -const postExprBlocks = { - nkStmtList, nkStmtListExpr, nkOfBranch, nkElifBranch, nkElse, nkExceptBranch, - nkFinally, nkDo -} - proc postStatements( g: var TOutput, n: PNode, start: int, skipDo: bool, skipColon = false ) = @@ -1516,7 +1542,7 @@ proc gsub(g: var TOutput, n: PNode, flags: SubFlags, extra: int) = false ind = condIndent(g, doPars) - accentedName(g, n[0], flags = (flags * {sfStackDot}) + {sfStackDotInCall}) + accentedName(g, n[0]) var i = 1 while i < n.len and n[i].kind notin postExprBlocks: @@ -2194,8 +2220,7 @@ proc gsub(g: var TOutput, n: PNode, flags: SubFlags, extra: int) = # see hasSignature - it would be nicer to remove them when unncessary if n.len >= 1: let retExtra = - extra + - ( + extra + ( if n.len > 0 and n[0].kind != nkEmpty: lsub(g, n[0]) + len(": ") else: diff --git a/tests/after/exprs.nim b/tests/after/exprs.nim index d0fe17c..8a928e7 100644 --- a/tests/after/exprs.nim +++ b/tests/after/exprs.nim @@ -145,8 +145,7 @@ aaaaaaa.bbbbbbbbb .longdotcall().ccccccccc.dddddddddd.eeeeeeeee .sdcsd(a0000000, b000000, c000000).fffffff.ggggggg.hhhhhhhh.csdcsdcs.sdcsdcsd.csdcsdcsdcsd.csdcsdcs.dcsdcsdcsdcs.sdc -mynums = - myNums +mynums = myNums .replace1("one", "o1ne") .replace2("two", "t2wo") .replace3("three", "t3hree") @@ -170,3 +169,18 @@ discard (cccccccccccccccccccccc and ddddddddddddddddddd) ) ) + +# Dot expressions +let test2 = someSimpleResult.fff(v).valueOr: + 3 + +let test2 = someSimpleResult( + aaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbb, ccccccccccccccccccccc, ddddddddddddd +).valueOr: + 3 + +var aaaaaaaaaaaaaaaaaaaaaaaa = + bbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccc[].ddddddddddddddddddddd + +aaaaaaaaaaaaaaaaaaaaaaaa = + bbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccc[].ddddddddddddddddddddd diff --git a/tests/after/exprs.nim.nph.yaml b/tests/after/exprs.nim.nph.yaml index b595ec7..932b2c4 100644 --- a/tests/after/exprs.nim.nph.yaml +++ b/tests/after/exprs.nim.nph.yaml @@ -1885,3 +1885,96 @@ sons: ident: "cccccccccccccccccccccc" - kind: "nkIdent" ident: "ddddddddddddddddddd" + - kind: "nkCommentStmt" + "comment": "# Dot expressions" + - kind: "nkLetSection" + sons: + - kind: "nkIdentDefs" + sons: + - kind: "nkIdent" + ident: "test2" + - kind: "nkEmpty" + - kind: "nkCall" + sons: + - kind: "nkDotExpr" + sons: + - kind: "nkCall" + sons: + - kind: "nkDotExpr" + sons: + - kind: "nkIdent" + ident: "someSimpleResult" + - kind: "nkIdent" + ident: "fff" + - kind: "nkIdent" + ident: "v" + - kind: "nkIdent" + ident: "valueOr" + - kind: "nkStmtList" + sons: + - kind: "nkIntLit" + intVal: 3 + - kind: "nkLetSection" + sons: + - kind: "nkIdentDefs" + sons: + - kind: "nkIdent" + ident: "test2" + - kind: "nkEmpty" + - kind: "nkCall" + sons: + - kind: "nkDotExpr" + sons: + - kind: "nkCall" + sons: + - kind: "nkIdent" + ident: "someSimpleResult" + - kind: "nkIdent" + ident: "aaaaaaaaaaaaaaaaaaa" + - kind: "nkIdent" + ident: "bbbbbbbbbbbbb" + - kind: "nkIdent" + ident: "ccccccccccccccccccccc" + - kind: "nkIdent" + ident: "ddddddddddddd" + - kind: "nkIdent" + ident: "valueOr" + - kind: "nkStmtList" + sons: + - kind: "nkIntLit" + intVal: 3 + - kind: "nkVarSection" + sons: + - kind: "nkIdentDefs" + sons: + - kind: "nkIdent" + ident: "aaaaaaaaaaaaaaaaaaaaaaaa" + - kind: "nkEmpty" + - kind: "nkDotExpr" + sons: + - kind: "nkBracketExpr" + sons: + - kind: "nkDotExpr" + sons: + - kind: "nkIdent" + ident: "bbbbbbbbbbbbbbbbbbbb" + - kind: "nkIdent" + ident: "cccccccccccccccccccc" + - kind: "nkIdent" + ident: "ddddddddddddddddddddd" + - kind: "nkAsgn" + sons: + - kind: "nkIdent" + ident: "aaaaaaaaaaaaaaaaaaaaaaaa" + - kind: "nkDotExpr" + sons: + - kind: "nkBracketExpr" + sons: + - kind: "nkDotExpr" + sons: + - kind: "nkIdent" + ident: "bbbbbbbbbbbbbbbbbbbb" + - kind: "nkIdent" + ident: "cccccccccccccccccccc" + - kind: "nkIdent" + ident: "ddddddddddddddddddddd" diff --git a/tests/after/postexprs.nim b/tests/after/postexprs.nim index da6f108..72867bb 100644 --- a/tests/after/postexprs.nim +++ b/tests/after/postexprs.nim @@ -92,10 +92,7 @@ of a: else: discard -discard - ( - aaa.bbb - .exec do(res: int64): - size = res - ) - .ccc() +discard ( + aaa.bbb.exec do(res: int64): + size = res +).ccc() diff --git a/tests/before/exprs.nim b/tests/before/exprs.nim index ec876f7..7d4e5f6 100644 --- a/tests/before/exprs.nim +++ b/tests/before/exprs.nim @@ -114,3 +114,12 @@ let xxxxxxxxx = block: let yyyyyyyyyy = aaaaaaaaaaaaaaaaaaaaaaaaa.ffffffffffffff(aaaaaaaaa, bbbbbbbbbbbbbbbbbb, cccccccccccccccccccc) discard aaaaaaaaa and (aaaaaaaaaaaaaaaaaaaaaaaa and (aaaaaaaaaaaaaaaaaaaaa and bbbbbbbbbbbbbbbbbbbbbbb and (cccccccccccccccccccccc and ddddddddddddddddddd))) + +# Dot expressions +let test2 = someSimpleResult.fff(v).valueOr: 3 + +let test2 = someSimpleResult(aaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbb, ccccccccccccccccccccc, ddddddddddddd).valueOr: 3 + +var aaaaaaaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccc[].ddddddddddddddddddddd + +aaaaaaaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbbbbbbb.cccccccccccccccccccc[].ddddddddddddddddddddd diff --git a/tests/before/exprs.nim.nph.yaml b/tests/before/exprs.nim.nph.yaml index 51b183c..8ef571f 100644 --- a/tests/before/exprs.nim.nph.yaml +++ b/tests/before/exprs.nim.nph.yaml @@ -1885,3 +1885,96 @@ sons: ident: "cccccccccccccccccccccc" - kind: "nkIdent" ident: "ddddddddddddddddddd" + - kind: "nkCommentStmt" + "comment": "# Dot expressions" + - kind: "nkLetSection" + sons: + - kind: "nkIdentDefs" + sons: + - kind: "nkIdent" + ident: "test2" + - kind: "nkEmpty" + - kind: "nkCall" + sons: + - kind: "nkDotExpr" + sons: + - kind: "nkCall" + sons: + - kind: "nkDotExpr" + sons: + - kind: "nkIdent" + ident: "someSimpleResult" + - kind: "nkIdent" + ident: "fff" + - kind: "nkIdent" + ident: "v" + - kind: "nkIdent" + ident: "valueOr" + - kind: "nkStmtList" + sons: + - kind: "nkIntLit" + intVal: 3 + - kind: "nkLetSection" + sons: + - kind: "nkIdentDefs" + sons: + - kind: "nkIdent" + ident: "test2" + - kind: "nkEmpty" + - kind: "nkCall" + sons: + - kind: "nkDotExpr" + sons: + - kind: "nkCall" + sons: + - kind: "nkIdent" + ident: "someSimpleResult" + - kind: "nkIdent" + ident: "aaaaaaaaaaaaaaaaaaa" + - kind: "nkIdent" + ident: "bbbbbbbbbbbbb" + - kind: "nkIdent" + ident: "ccccccccccccccccccccc" + - kind: "nkIdent" + ident: "ddddddddddddd" + - kind: "nkIdent" + ident: "valueOr" + - kind: "nkStmtList" + sons: + - kind: "nkIntLit" + intVal: 3 + - kind: "nkVarSection" + sons: + - kind: "nkIdentDefs" + sons: + - kind: "nkIdent" + ident: "aaaaaaaaaaaaaaaaaaaaaaaa" + - kind: "nkEmpty" + - kind: "nkDotExpr" + sons: + - kind: "nkBracketExpr" + sons: + - kind: "nkDotExpr" + sons: + - kind: "nkIdent" + ident: "bbbbbbbbbbbbbbbbbbbb" + - kind: "nkIdent" + ident: "cccccccccccccccccccc" + - kind: "nkIdent" + ident: "ddddddddddddddddddddd" + - kind: "nkAsgn" + sons: + - kind: "nkIdent" + ident: "aaaaaaaaaaaaaaaaaaaaaaaa" + - kind: "nkDotExpr" + sons: + - kind: "nkBracketExpr" + sons: + - kind: "nkDotExpr" + sons: + - kind: "nkIdent" + ident: "bbbbbbbbbbbbbbbbbbbb" + - kind: "nkIdent" + ident: "cccccccccccccccccccc" + - kind: "nkIdent" + ident: "ddddddddddddddddddddd"