diff --git a/changelog.md b/changelog.md index 4aa22b9d7a..165518bd7c 100644 --- a/changelog.md +++ b/changelog.md @@ -61,6 +61,22 @@ - `paramCount` & `paramStr` are now defined in os.nim instead of nimscript.nim for nimscript/nimble. - `dollars.$` now works for unsigned ints with `nim js` +- `sugar.=>` and `sugar.->` changes: Previously `(x, y: int)` was transformed + into `(x: auto, y: int)`, it now becomes `(x: int, y: int)` in consistency + with regular proc definitions (although you cannot use semicolons). + + Pragmas and using a name are now allowed on the lefthand side of `=>`. Here + is an aggregate example of these changes: + ```nim + import sugar + + foo(x, y: int) {.noSideEffect.} => x + y + + # is transformed into + + proc foo(x: int, y: int): auto {.noSideEffect.} = x + y + ``` + ## Language changes - In newruntime it is now allowed to assign discriminator field without restrictions as long as case object doesn't have custom destructor. Discriminator value doesn't have to be a constant either. If you have custom destructor for case object and you do want to freely assign discriminator fields, it is recommended to refactor object into 2 objects like this: ```nim diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim index e0518f5ee1..99af26c993 100644 --- a/lib/pure/htmlgen.nim +++ b/lib/pure/htmlgen.nim @@ -64,7 +64,7 @@ proc getIdent(e: NimNode): string {.compileTime.} = result = getIdent(e[0]) for i in 1 .. e.len-1: result.add getIdent(e[i]) - else: error("cannot extract identifier from node: " & toStrLit(e).strVal) + else: error("cannot extract identifier from node: " & toStrLit(e).strVal, e) proc delete[T](s: var seq[T], attr: T): bool = var idx = find(s, attr) @@ -96,14 +96,14 @@ proc xmlCheckedTag*(argsList: NimNode, tag: string, optAttr = "", reqAttr = "", result.add(argsList[i][1]) result.add(newStrLitNode("\"")) else: - error("invalid attribute for '" & tag & "' element: " & name) + error("invalid attribute for '" & tag & "' element: " & name, argsList[i]) # check each required attribute exists: if req.len > 0: - error(req[0] & " attribute for '" & tag & "' element expected") + error(req[0] & " attribute for '" & tag & "' element expected", argsList) if isLeaf: for i in 0 ..< argsList.len: if argsList[i].kind != nnkExprEqExpr: - error("element " & tag & " cannot be nested") + error("element " & tag & " cannot be nested", argsList[i]) result.add(newStrLitNode(" />")) else: result.add(newStrLitNode(">")) diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index a1f80ad767..bb68085aad 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -1295,7 +1295,7 @@ macro genEnumStmt(typ: typedesc, argSym: typed, default: typed): untyped = foundFields.add fStr else: error("Ambiguous enums cannot be parsed, field " & $fStr & - " appears multiple times!") + " appears multiple times!", f) inc fNum # finally add else branch to raise or use default if default == nil: diff --git a/lib/pure/sugar.nim b/lib/pure/sugar.nim index 062341ccb6..dbc60b8a9c 100644 --- a/lib/pure/sugar.nim +++ b/lib/pure/sugar.nim @@ -11,16 +11,25 @@ ## macro system. import std/private/since -import macros -import typetraits +import macros, typetraits + +proc checkPragma(ex, prag: var NimNode) = + since (1, 3): + if ex.kind == nnkPragmaExpr: + prag = ex[1] + if ex[0].kind == nnkPar and ex[0].len == 1: + ex = ex[0][0] + else: + ex = ex[0] proc createProcType(p, b: NimNode): NimNode {.compileTime.} = - #echo treeRepr(p) - #echo treeRepr(b) result = newNimNode(nnkProcTy) - var formalParams = newNimNode(nnkFormalParams) + var + formalParams = newNimNode(nnkFormalParams).add(b) + p = p + prag = newEmptyNode() - formalParams.add b + checkPragma(p, prag) case p.kind of nnkPar, nnkTupleConstr: @@ -44,9 +53,7 @@ proc createProcType(p, b: NimNode): NimNode {.compileTime.} = formalParams.add identDefs result.add formalParams - result.add newEmptyNode() - #echo(treeRepr(result)) - #echo(result.toStrLit()) + result.add prag macro `=>`*(p, b: untyped): untyped = ## Syntax sugar for anonymous procedures. @@ -58,56 +65,75 @@ macro `=>`*(p, b: untyped): untyped = ## ## passTwoAndTwo((x, y) => x + y) # 4 - #echo treeRepr(p) - #echo(treeRepr(b)) - var params: seq[NimNode] = @[newIdentNode("auto")] + var + params = @[ident"auto"] + name = newEmptyNode() + kind = nnkLambda + pragma = newEmptyNode() + p = p + + checkPragma(p, pragma) + + if p.kind == nnkInfix and p[0].kind == nnkIdent and p[0].eqIdent"->": + params[0] = p[2] + p = p[1] + + checkPragma(p, pragma) # check again after -> transform + + since (1, 3): + if p.kind == nnkCall: + # foo(x, y) => x + y + kind = nnkProcDef + name = p[0] + let newP = newNimNode(nnkPar) + for i in 1..