Showing with 833 additions and 217 deletions.
  1. +12 −0 changelog.md
  2. +2 −2 compiler/ccgstmts.nim
  3. +2 −2 compiler/cgen.nim
  4. +1 −0 compiler/condsyms.nim
  5. +2 −2 compiler/installer.ini
  6. +42 −14 compiler/jsgen.nim
  7. +7 −5 compiler/lambdalifting.nim
  8. +5 −1 compiler/parser.nim
  9. +2 −1 compiler/platform.nim
  10. +7 −6 compiler/pragmas.nim
  11. +1 −1 compiler/types.nim
  12. +19 −3 compiler/varpartitions.nim
  13. +2 −10 compiler/vmgen.nim
  14. +10 −1 compiler/vmops.nim
  15. +10 −21 doc/manual.rst
  16. +1 −1 koch.nim
  17. +9 −11 lib/pure/asynchttpserver.nim
  18. +1 −1 lib/pure/collections/sequtils.nim
  19. +0 −1 lib/pure/collections/tables.nim
  20. +1 −1 lib/pure/httpclient.nim
  21. +1 −1 lib/pure/includes/oserr.nim
  22. +16 −3 lib/pure/net.nim
  23. +40 −18 lib/pure/osproc.nim
  24. +57 −14 lib/pure/ssl_certs.nim
  25. +1 −1 lib/pure/sugar.nim
  26. +19 −17 lib/pure/typetraits.nim
  27. +1 −1 lib/pure/uri.nim
  28. +50 −35 lib/std/sha1.nim
  29. +18 −4 lib/system.nim
  30. +4 −4 lib/system/alloc.nim
  31. +1 −1 lib/system/arc.nim
  32. +1 −2 lib/system/assertions.nim
  33. +3 −1 lib/system/assign.nim
  34. +11 −4 lib/system/io.nim
  35. +1 −1 lib/system/jssys.nim
  36. +4 −4 lib/system/mmdisp.nim
  37. +7 −6 lib/system/strs_v2.nim
  38. +1 −0 testament/categories.nim
  39. +3 −3 testament/important_packages.nim
  40. +84 −2 tests/arc/topt_no_cursor.nim
  41. +16 −0 tests/arc/trepr.nim
  42. +37 −0 tests/assign/tobject_assign.nim
  43. +1 −1 tests/destructor/tbintree2.nim
  44. +31 −1 tests/destructor/tnewruntime_strutils.nim
  45. +1 −1 tests/errmsgs/tgcsafety.nim
  46. +22 −0 tests/gc/trace_globals.nim
  47. +58 −0 tests/js/tbigint_backend.nim
  48. +9 −1 tests/js/tnilstrs.nim
  49. +6 −1 tests/metatype/ttypetraits.nim
  50. +27 −0 tests/openarray/topenarray.nim
  51. +115 −0 tests/parser/tpostexprblocks.nim
  52. +7 −0 tests/proc/tlambdapragma.nim
  53. +1 −1 tests/stdlib/thttpclient_ssl.nim
  54. +13 −0 tests/stdlib/tmath.nim
  55. +24 −1 tests/system/tdollars.nim
  56. +4 −0 tests/vm/tvmops.nim
  57. +2 −4 tools/dochack/dochack.nim
12 changes: 12 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@

## Standard library additions and changes

- On Windows the SSL library now checks for valid certificates.
It uses the `cacert.pem` file for this purpose which was extracted
from `https://curl.se/ca/cacert.pem`. Besides
the OpenSSL DLLs (e.g. libssl-1_1-x64.dll, libcrypto-1_1-x64.dll) you
now also need to ship `cacert.pem` with your `.exe` file.


- Make `{.requiresInit.}` pragma to work for `distinct` types.

- Added a macros `enumLen` for returning the number of items in an enum to the
`typetraits.nim` module.

- `prelude` now works with the JavaScript target.

- Added `ioutils` module containing `duplicate` and `duplicateTo` to duplicate `FileHandle` using C function `dup` and `dup2`.
Expand Down
4 changes: 2 additions & 2 deletions compiler/ccgstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ proc getTraverseProc(p: BProc, v: PSym): Rope =

proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) =
if sfThread in v.flags:
appcg(p.module, p.module.initProc.procSec(cpsInit),
appcg(p.module, p.module.preInitProc.procSec(cpsInit),
"$n\t#nimRegisterThreadLocalMarker($1);$n$n", [traverseProc])
else:
appcg(p.module, p.module.initProc.procSec(cpsInit),
appcg(p.module, p.module.preInitProc.procSec(cpsInit),
"$n\t#nimRegisterGlobalMarker($1);$n$n", [traverseProc])

proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} =
Expand Down
4 changes: 2 additions & 2 deletions compiler/cgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1686,7 +1686,7 @@ proc genInitCode(m: BModule) =
writeSection(preInitProc, cpsLocals)
writeSection(preInitProc, cpsInit, m.hcrOn)
writeSection(preInitProc, cpsStmts)
prc.addf("}$N", [])
prc.addf("}/* preInitProc end */$N", [])
when false:
m.initProc.blocks[0].sections[cpsLocals].add m.preInitProc.s(cpsLocals)
m.initProc.blocks[0].sections[cpsInit].prepend m.preInitProc.s(cpsInit)
Expand Down Expand Up @@ -2052,7 +2052,7 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
if m.config.exc == excGoto and getCompilerProc(graph, "nimTestErrorFlag") != nil:
discard cgsym(m, "nimTestErrorFlag")

if {optGenStaticLib, optGenDynLib} * m.config.globalOptions == {}:
if {optGenStaticLib, optGenDynLib, optNoMain} * m.config.globalOptions == {}:
for i in countdown(high(graph.globalDestructors), 0):
n.add graph.globalDestructors[i]
if passes.skipCodegen(m.config, n): return
Expand Down
1 change: 1 addition & 0 deletions compiler/condsyms.nim
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,4 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasStacktracesModule")
defineSymbol("nimHasEffectTraitsModule")
defineSymbol("nimHasCastPragmaBlocks")
defineSymbol("nimHasJsBigIntBackend")
4 changes: 2 additions & 2 deletions compiler/installer.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Name: "Nim"
Version: "$version"
Platforms: """
windows: i386;amd64
linux: i386;hppa;ia64;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv64
macosx: i386;amd64;powerpc64
linux: i386;hppa;ia64;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv32;riscv64
macosx: i386;amd64;powerpc64;arm64
solaris: i386;amd64;sparc;sparc64
freebsd: i386;amd64;powerpc64;arm;arm64;riscv64;sparc64;mips;mipsel;mips64;mips64el;powerpc;powerpc64el
netbsd: i386;amd64
Expand Down
56 changes: 42 additions & 14 deletions compiler/jsgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,28 @@ The JS code generator contains only 2 tricks:
Trick 1
-------
Some locations (for example 'var int') require "fat pointers" (``etyBaseIndex``)
Some locations (for example 'var int') require "fat pointers" (`etyBaseIndex`)
which are pairs (array, index). The derefence operation is then 'array[index]'.
Check ``mapType`` for the details.
Check `mapType` for the details.
Trick 2
-------
It is preferable to generate '||' and '&&' if possible since that is more
idiomatic and hence should be friendlier for the JS JIT implementation. However
code like ``foo and (let bar = baz())`` cannot be translated this way. Instead
the expressions need to be transformed into statements. ``isSimpleExpr``
code like `foo and (let bar = baz())` cannot be translated this way. Instead
the expressions need to be transformed into statements. `isSimpleExpr`
implements the required case distinction.
"""


import
ast, strutils, trees, magicsys, options,
nversion, msgs, idents, types, tables,
ropes, math, passes, ccgutils, wordrecg, renderer,
intsets, cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils,
transf, injectdestructors, sourcemap, json, sets
ast, trees, magicsys, options,
nversion, msgs, idents, types,
ropes, passes, ccgutils, wordrecg, renderer,
cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils,
transf, injectdestructors, sourcemap

import std/[json, sets, math, tables, intsets, strutils]

from modulegraphs import ModuleGraph, PPassContext

Expand Down Expand Up @@ -1345,7 +1346,15 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
of nkStmtListExpr:
if n.len == 1: gen(p, n[0], r)
else: internalError(p.config, n[0].info, "genAddr for complex nkStmtListExpr")
else: internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
of nkCallKinds:
if n[0].typ.kind == tyOpenArray:
# 'var openArray' for instance produces an 'addr' but this is harmless:
# namely toOpenArray(a, 1, 3)
gen(p, n[0], r)
else:
internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
else:
internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)

proc attachProc(p: PProc; content: Rope; s: PSym) =
p.g.code.add(content)
Expand Down Expand Up @@ -1672,7 +1681,10 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
var t = skipTypes(typ, abstractInst)
case t.kind
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar:
result = putToSeq("0", indirect)
if $t.sym.loc.r == "bigint":
result = putToSeq("0n", indirect)
else:
result = putToSeq("0", indirect)
of tyFloat..tyFloat128:
result = putToSeq("0.0", indirect)
of tyRange, tyGenericInst, tyAlias, tySink, tyOwned:
Expand Down Expand Up @@ -1994,7 +2006,9 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
gen(p, n[2], rhs)

if skipTypes(n[1].typ, abstractVarRange).kind == tyCString:
r.res = "$1 += $2;" % [lhs.rdLoc, rhs.rdLoc]
let (b, tmp) = maybeMakeTemp(p, n[2], rhs)
r.res = "if (null != $1) { if (null == $2) $2 = $3; else $2 += $3; }" %
[b, lhs.rdLoc, tmp]
else:
let (a, tmp) = maybeMakeTemp(p, n[1], lhs)
r.res = "$1.push.apply($3, $2);" % [a, rhs.rdLoc, tmp]
Expand Down Expand Up @@ -2045,9 +2059,23 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
of mDestroy: discard "ignore calls to the default destructor"
of mOrd: genOrd(p, n, r)
of mLengthStr, mLengthSeq, mLengthOpenArray, mLengthArray:
unaryExpr(p, n, r, "", "($1).length")
var x: TCompRes
gen(p, n[1], x)
if skipTypes(n[1].typ, abstractInst).kind == tyCString:
let (a, tmp) = maybeMakeTemp(p, n[1], x)
r.res = "(($1) == null ? 0 : ($2).length)" % [a, tmp]
else:
r.res = "($1).length" % [x.rdLoc]
r.kind = resExpr
of mHigh:
unaryExpr(p, n, r, "", "(($1).length-1)")
var x: TCompRes
gen(p, n[1], x)
if skipTypes(n[1].typ, abstractInst).kind == tyCString:
let (a, tmp) = maybeMakeTemp(p, n[1], x)
r.res = "(($1) == null ? -1 : ($2).length - 1)" % [a, tmp]
else:
r.res = "($1).length - 1" % [x.rdLoc]
r.kind = resExpr
of mInc:
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
binaryUintExpr(p, n, r, "+", true)
Expand Down
12 changes: 7 additions & 5 deletions compiler/lambdalifting.nim
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,11 @@ proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} =
result = conf.backend == backendJs and not isCompileTime

proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; owner: PSym) =
createTypeBoundOps(g, nil, refType.lastSon, info)
createTypeBoundOps(g, nil, refType, info)
if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions:
owner.flags.incl sfInjectDestructors
if owner.kind != skMacro:
createTypeBoundOps(g, nil, refType.lastSon, info)
createTypeBoundOps(g, nil, refType, info)
if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions:
owner.flags.incl sfInjectDestructors

proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
# transforms (iter) to (let env = newClosure[iter](); (iter, env))
Expand Down Expand Up @@ -611,7 +612,8 @@ proc rawClosureCreation(owner: PSym;
let fieldAccess = indirectAccess(env, local, env.info)
# add ``env.param = param``
result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info))
createTypeBoundOps(d.graph, nil, fieldAccess.typ, env.info)
if owner.kind != skMacro:
createTypeBoundOps(d.graph, nil, fieldAccess.typ, env.info)
if tfHasAsgn in fieldAccess.typ.flags or optSeqDestructors in d.graph.config.globalOptions:
owner.flags.incl sfInjectDestructors

Expand Down
6 changes: 5 additions & 1 deletion compiler/parser.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
#| | IND{=} 'of' exprList ':' stmt
#| | IND{=} 'elif' expr ':' stmt
#| | IND{=} 'except' exprList ':' stmt
#| | IND{=} 'finally' ':' stmt
#| | IND{=} 'else' ':' stmt )*
result = x
if p.tok.indent >= 0: return
Expand Down Expand Up @@ -1364,6 +1365,9 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
of tkExcept:
nextBlock = newNodeP(nkExceptBranch, p)
exprList(p, tkColon, nextBlock)
of tkFinally:
nextBlock = newNodeP(nkFinally, p)
getTok(p)
of tkElse:
nextBlock = newNodeP(nkElse, p)
getTok(p)
Expand All @@ -1374,7 +1378,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
nextBlock.flags.incl nfBlockArg
result.add nextBlock

if nextBlock.kind == nkElse: break
if nextBlock.kind in {nkElse, nkFinally}: break
else:
if openingParams.kind != nkEmpty:
parMessage(p, "expected ':'")
Expand Down
3 changes: 2 additions & 1 deletion compiler/platform.nim
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ type
cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64,
cpuPowerpc64el, cpuSparc, cpuVm, cpuHppa, cpuIa64, cpuAmd64, cpuMips,
cpuMipsel, cpuArm, cpuArm64, cpuJS, cpuNimVM, cpuAVR, cpuMSP430,
cpuSparc64, cpuMips64, cpuMips64el, cpuRiscV64, cpuEsp, cpuWasm32
cpuSparc64, cpuMips64, cpuMips64el, cpuRiscV32, cpuRiscV64, cpuEsp, cpuWasm32

type
TEndian* = enum
Expand Down Expand Up @@ -226,6 +226,7 @@ const
(name: "sparc64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
(name: "mips64", intSize: 64, endian: bigEndian, floatSize: 64, bit: 64),
(name: "mips64el", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
(name: "riscv32", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
(name: "riscv64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64),
(name: "esp", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32),
(name: "wasm32", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32)]
Expand Down
13 changes: 7 additions & 6 deletions compiler/pragmas.nim
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const

const
declPragmas = {wImportc, wImportObjC, wImportCpp, wImportJs, wExportc, wExportCpp,
wExportNims, wExtern, wDeprecated, wNodecl, wError, wUsed, wAlign}
wExportNims, wExtern, wDeprecated, wNodecl, wError, wUsed}
## common pragmas for declarations, to a good approximation
procPragmas* = declPragmas + {FirstCallConv..LastCallConv,
wMagic, wNoSideEffect, wSideEffect, wNoreturn, wNosinks, wDynlib, wHeader,
Expand Down Expand Up @@ -54,22 +54,23 @@ const
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wTrMacros, wEffects, wNoForward, wReorder, wComputedGoto,
wInjectStmt, wExperimental, wThis, wUsed, wInvariant, wAssume, wAssert}
lambdaPragmas* = declPragmas + {FirstCallConv..LastCallConv,
lambdaPragmas* = {FirstCallConv..LastCallConv,
wNoSideEffect, wSideEffect, wNoreturn, wNosinks, wDynlib, wHeader,
wThread, wAsmNoStackFrame,
wRaises, wLocks, wTags, wRequires, wEnsures,
wGcSafe, wCodegenDecl} - {wExportNims, wError, wUsed} # why exclude these?
wGcSafe, wCodegenDecl, wNoInit}
typePragmas* = declPragmas + {wMagic, wAcyclic,
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wShallow,
wIncompleteStruct, wCompleteStruct, wByCopy, wByRef,
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
wBorrow, wGcSafe, wPartial, wExplain, wPackage}
fieldPragmas* = declPragmas + {
wGuard, wBitsize, wCursor, wRequiresInit, wNoalias} - {wExportNims, wNodecl} # why exclude these?
fieldPragmas* = declPragmas + {wGuard, wBitsize, wCursor,
wRequiresInit, wNoalias, wAlign} - {wExportNims, wNodecl} # why exclude these?
varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,
wMagic, wHeader, wCompilerProc, wCore, wDynlib,
wNoInit, wCompileTime, wGlobal,
wGensym, wInject, wCodegenDecl, wGuard, wGoto, wCursor, wNoalias}
wGensym, wInject, wCodegenDecl,
wGuard, wGoto, wCursor, wNoalias, wAlign}
constPragmas* = declPragmas + {wHeader, wMagic,
wGensym, wInject,
wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
Expand Down
2 changes: 1 addition & 1 deletion compiler/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const
tyInferred, tySink, tyLent, tyOwned}
# typedescX is used if we're sure tyTypeDesc should be included (or skipped)
typedescPtrs* = abstractPtrs + {tyTypeDesc}
typedescInst* = abstractInst + {tyTypeDesc, tyOwned}
typedescInst* = abstractInst + {tyTypeDesc, tyOwned, tyUserTypeClass}

proc invalidGenericInst*(f: PType): bool =
result = f.kind == tyGenericInst and lastSon(f) == nil
Expand Down
22 changes: 19 additions & 3 deletions compiler/varpartitions.nim
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type
ownsData,
preventCursor,
isReassigned,
isConditionallyReassigned,
viewDoesMutate,
viewBorrowsFromConst

Expand Down Expand Up @@ -98,6 +99,7 @@ type
goals: set[Goal]
unanalysableMutation: bool
inAsgnSource, inConstructor, inNoSideEffectSection: int
inConditional, inLoop: int
owner: PSym
config: ConfigRef

Expand Down Expand Up @@ -748,6 +750,13 @@ proc traverse(c: var Partitions; n: PNode) =
else:
for child in n: traverse(c, child)

proc markAsReassigned(c: var Partitions; vid: int) {.inline.} =
c.s[vid].flags.incl isReassigned
if c.inConditional > 0 and c.inLoop > 0:
# bug #17033: live ranges with loops and conditionals are too
# complex for our current analysis, so we prevent the cursorfication.
c.s[vid].flags.incl isConditionallyReassigned

proc computeLiveRanges(c: var Partitions; n: PNode) =
# first pass: Compute live ranges for locals.
# **Watch out!** We must traverse the tree like 'traverse' does
Expand Down Expand Up @@ -777,7 +786,7 @@ proc computeLiveRanges(c: var Partitions; n: PNode) =
if n[1].kind == nkSym and (c.s[vid].reassignedTo == 0 or c.s[vid].reassignedTo == n[1].sym.id):
c.s[vid].reassignedTo = n[1].sym.id
else:
c.s[vid].flags.incl isReassigned
markAsReassigned(c, vid)

of nkSym:
dec c.abstractTime
Expand All @@ -804,7 +813,7 @@ proc computeLiveRanges(c: var Partitions; n: PNode) =
if not paramType.isCompileTimeOnly and paramType.kind == tyVar:
let vid = variableId(c, it.sym)
if vid >= 0:
c.s[vid].flags.incl isReassigned
markAsReassigned(c, vid)

of nkAddr, nkHiddenAddr:
computeLiveRanges(c, n[0])
Expand All @@ -822,7 +831,13 @@ proc computeLiveRanges(c: var Partitions; n: PNode) =
# while cond:
# mutate(graph)
# connect(graph, cursorVar)
inc c.inLoop
for child in n: computeLiveRanges(c, child)
inc c.inLoop
of nkElifBranch, nkElifExpr, nkElse, nkOfBranch:
inc c.inConditional
for child in n: computeLiveRanges(c, child)
dec c.inConditional
else:
for child in n: computeLiveRanges(c, child)

Expand Down Expand Up @@ -896,7 +911,8 @@ proc computeCursors*(s: PSym; n: PNode; config: ConfigRef) =
var par = computeGraphPartitions(s, n, config, {cursorInference})
for i in 0 ..< par.s.len:
let v = addr(par.s[i])
if v.flags * {ownsData, preventCursor} == {} and v.sym.kind notin {skParam, skResult} and
if v.flags * {ownsData, preventCursor, isConditionallyReassigned} == {} and
v.sym.kind notin {skParam, skResult} and
v.sym.flags * {sfThread, sfGlobal} == {} and hasDestructor(v.sym.typ) and
v.sym.typ.skipTypes({tyGenericInst, tyAlias}).kind != tyOwned:
let rid = root(par, i)
Expand Down
12 changes: 2 additions & 10 deletions compiler/vmgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1952,14 +1952,6 @@ proc genProc*(c: PCtx; s: PSym): int

proc matches(s: PSym; x: string): bool =
let y = x.split('.')
var s = s
for i in 1..y.len:
if s == nil or (y[^i].cmpIgnoreStyle(s.name.s) != 0 and y[^i] != "*"):
return false
s = s.owner
result = true

proc matches(s: PSym; y: varargs[string]): bool =
var s = s
for i in 1..y.len:
if s == nil or (y[^i].cmpIgnoreStyle(s.name.s) != 0 and y[^i] != "*"):
Expand Down Expand Up @@ -2022,11 +2014,11 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
elif s.kind == skMethod:
localError(c.config, n.info, "cannot call method " & s.name.s &
" at compile time")
elif matches(s, "stdlib", "marshal", "to"):
elif matches(s, "stdlib.marshal.to"):
# XXX marshal load&store should not be opcodes, but use the
# general callback mechanisms.
genMarshalLoad(c, n, dest)
elif matches(s, "stdlib", "marshal", "$$"):
elif matches(s, "stdlib.marshal.$$"):
genMarshalStore(c, n, dest)
else:
genCall(c, n, dest)
Expand Down
Loading