Big compiler Cleanup (#14777)
This commit is contained in:
parent
f8c48fc186
commit
13e659cfec
53 changed files with 481 additions and 783 deletions
|
|
@ -17,20 +17,19 @@ export int128
|
||||||
|
|
||||||
type
|
type
|
||||||
TCallingConvention* = enum
|
TCallingConvention* = enum
|
||||||
ccNimCall, # nimcall, also the default
|
ccNimCall # nimcall, also the default
|
||||||
ccStdCall, # procedure is stdcall
|
ccStdCall # procedure is stdcall
|
||||||
ccCDecl, # cdecl
|
ccCDecl # cdecl
|
||||||
ccSafeCall, # safecall
|
ccSafeCall # safecall
|
||||||
ccSysCall, # system call
|
ccSysCall # system call
|
||||||
ccInline, # proc should be inlined
|
ccInline # proc should be inlined
|
||||||
ccNoInline, # proc should not be inlined
|
ccNoInline # proc should not be inlined
|
||||||
ccFastCall, # fastcall (pass parameters in registers)
|
ccFastCall # fastcall (pass parameters in registers)
|
||||||
ccThisCall, # thiscall (parameters are pushed right-to-left)
|
ccThisCall # thiscall (parameters are pushed right-to-left)
|
||||||
ccClosure, # proc has a closure
|
ccClosure # proc has a closure
|
||||||
ccNoConvention # needed for generating proper C procs sometimes
|
ccNoConvention # needed for generating proper C procs sometimes
|
||||||
|
|
||||||
const
|
const CallingConvToStr*: array[TCallingConvention, string] = ["nimcall", "stdcall",
|
||||||
CallingConvToStr*: array[TCallingConvention, string] = ["nimcall", "stdcall",
|
|
||||||
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "thiscall",
|
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "thiscall",
|
||||||
"closure", "noconv"]
|
"closure", "noconv"]
|
||||||
|
|
||||||
|
|
@ -1363,7 +1362,7 @@ proc newType*(kind: TTypeKind, owner: PSym): PType =
|
||||||
proc mergeLoc(a: var TLoc, b: TLoc) =
|
proc mergeLoc(a: var TLoc, b: TLoc) =
|
||||||
if a.k == low(a.k): a.k = b.k
|
if a.k == low(a.k): a.k = b.k
|
||||||
if a.storage == low(a.storage): a.storage = b.storage
|
if a.storage == low(a.storage): a.storage = b.storage
|
||||||
a.flags = a.flags + b.flags
|
a.flags.incl b.flags
|
||||||
if a.lode == nil: a.lode = b.lode
|
if a.lode == nil: a.lode = b.lode
|
||||||
if a.r == nil: a.r = b.r
|
if a.r == nil: a.r = b.r
|
||||||
|
|
||||||
|
|
@ -1388,7 +1387,7 @@ proc assignType*(dest, src: PType) =
|
||||||
# this fixes 'type TLock = TSysLock':
|
# this fixes 'type TLock = TSysLock':
|
||||||
if src.sym != nil:
|
if src.sym != nil:
|
||||||
if dest.sym != nil:
|
if dest.sym != nil:
|
||||||
dest.sym.flags = dest.sym.flags + (src.sym.flags-{sfExported})
|
dest.sym.flags.incl src.sym.flags-{sfExported}
|
||||||
if dest.sym.annex == nil: dest.sym.annex = src.sym.annex
|
if dest.sym.annex == nil: dest.sym.annex = src.sym.annex
|
||||||
mergeLoc(dest.sym.loc, src.sym.loc)
|
mergeLoc(dest.sym.loc, src.sym.loc)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1495,8 +1494,7 @@ proc isGCedMem*(t: PType): bool {.inline.} =
|
||||||
t.kind == tyProc and t.callConv == ccClosure
|
t.kind == tyProc and t.callConv == ccClosure
|
||||||
|
|
||||||
proc propagateToOwner*(owner, elem: PType; propagateHasAsgn = true) =
|
proc propagateToOwner*(owner, elem: PType; propagateHasAsgn = true) =
|
||||||
const HaveTheirOwnEmpty = {tySequence, tySet, tyPtr, tyRef, tyProc}
|
owner.flags.incl elem.flags * {tfHasMeta, tfTriggersCompileTime}
|
||||||
owner.flags = owner.flags + (elem.flags * {tfHasMeta, tfTriggersCompileTime})
|
|
||||||
if tfNotNil in elem.flags:
|
if tfNotNil in elem.flags:
|
||||||
if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvocation}:
|
if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvocation}:
|
||||||
owner.flags.incl tfNotNil
|
owner.flags.incl tfNotNil
|
||||||
|
|
|
||||||
|
|
@ -135,8 +135,7 @@ proc `$`[Key, Val](b: BTree[Key, Val]): string =
|
||||||
result = ""
|
result = ""
|
||||||
toString(b.root, "", result)
|
toString(b.root, "", result)
|
||||||
|
|
||||||
proc hasNext*[Key, Val](b: BTree[Key, Val]; index: int): bool =
|
proc hasNext*[Key, Val](b: BTree[Key, Val]; index: int): bool = index < b.entries
|
||||||
result = index < b.entries
|
|
||||||
|
|
||||||
proc countSubTree[Key, Val](it: Node[Key, Val]): int =
|
proc countSubTree[Key, Val](it: Node[Key, Val]): int =
|
||||||
if it.isInternal:
|
if it.isInternal:
|
||||||
|
|
|
||||||
|
|
@ -1653,7 +1653,7 @@ template genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, n[1], a)
|
initLocExpr(p, n[1], a)
|
||||||
a.r = ropecg(p.module, frmt, [rdLoc(a)])
|
a.r = ropecg(p.module, frmt, [rdLoc(a)])
|
||||||
a.flags = a.flags - {lfIndirect} # this flag should not be propagated here (not just for HCR)
|
a.flags.excl lfIndirect # this flag should not be propagated here (not just for HCR)
|
||||||
if d.k == locNone: getTemp(p, n.typ, d)
|
if d.k == locNone: getTemp(p, n.typ, d)
|
||||||
genAssignment(p, d, a, {})
|
genAssignment(p, d, a, {})
|
||||||
gcUsage(p.config, n)
|
gcUsage(p.config, n)
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ proc mergeRequired*(m: BModule): bool =
|
||||||
if m.s[i] != nil:
|
if m.s[i] != nil:
|
||||||
#echo "not empty: ", i, " ", m.s[i]
|
#echo "not empty: ", i, " ", m.s[i]
|
||||||
return true
|
return true
|
||||||
for i in low(TCProcSection)..high(TCProcSection):
|
for i in TCProcSection:
|
||||||
if m.initProc.s(i) != nil:
|
if m.initProc.s(i) != nil:
|
||||||
#echo "not empty: ", i, " ", m.initProc.s[i]
|
#echo "not empty: ", i, " ", m.initProc.s[i]
|
||||||
return true
|
return true
|
||||||
|
|
@ -292,7 +292,7 @@ proc mergeFiles*(cfilename: AbsoluteFile, m: BModule) =
|
||||||
var old: TMergeSections
|
var old: TMergeSections
|
||||||
readMergeSections(cfilename, old)
|
readMergeSections(cfilename, old)
|
||||||
# do the merge; old section before new section:
|
# do the merge; old section before new section:
|
||||||
for i in low(TCFileSection)..high(TCFileSection):
|
for i in TCFileSection:
|
||||||
m.s[i] = old.f[i] & m.s[i]
|
m.s[i] = old.f[i] & m.s[i]
|
||||||
for i in low(TCProcSection)..high(TCProcSection):
|
for i in TCProcSection:
|
||||||
m.initProc.s(i) = old.p[i] & m.initProc.s(i)
|
m.initProc.s(i) = old.p[i] & m.initProc.s(i)
|
||||||
|
|
|
||||||
|
|
@ -1498,7 +1498,7 @@ proc genPragma(p: BProc, n: PNode) =
|
||||||
of wEmit: genEmit(p, it)
|
of wEmit: genEmit(p, it)
|
||||||
of wInjectStmt:
|
of wInjectStmt:
|
||||||
var p = newProc(nil, p.module)
|
var p = newProc(nil, p.module)
|
||||||
p.options = p.options - {optLineTrace, optStackTrace}
|
p.options.excl {optLineTrace, optStackTrace}
|
||||||
genStmts(p, it[1])
|
genStmts(p, it[1])
|
||||||
p.module.injectStmt = p.s(cpsStmts)
|
p.module.injectStmt = p.s(cpsStmts)
|
||||||
else: discard
|
else: discard
|
||||||
|
|
|
||||||
|
|
@ -681,7 +681,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
|
||||||
[loadlib, genStringLiteral(m, lib.path)])
|
[loadlib, genStringLiteral(m, lib.path)])
|
||||||
else:
|
else:
|
||||||
var p = newProc(nil, m)
|
var p = newProc(nil, m)
|
||||||
p.options = p.options - {optStackTrace}
|
p.options.excl optStackTrace
|
||||||
p.flags.incl nimErrorFlagDisabled
|
p.flags.incl nimErrorFlagDisabled
|
||||||
var dest: TLoc
|
var dest: TLoc
|
||||||
initLoc(dest, locTemp, lib.path, OnStack)
|
initLoc(dest, locTemp, lib.path, OnStack)
|
||||||
|
|
|
||||||
|
|
@ -485,7 +485,6 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||||
if ns:
|
if ns:
|
||||||
needsSplit = true
|
needsSplit = true
|
||||||
var tmp: PSym
|
var tmp: PSym
|
||||||
var s: PNode
|
|
||||||
let isExpr = not isEmptyType(n.typ)
|
let isExpr = not isEmptyType(n.typ)
|
||||||
if isExpr:
|
if isExpr:
|
||||||
tmp = ctx.newTempVar(n.typ)
|
tmp = ctx.newTempVar(n.typ)
|
||||||
|
|
@ -742,8 +741,6 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||||
result.add(n)
|
result.add(n)
|
||||||
|
|
||||||
of nkWhileStmt:
|
of nkWhileStmt:
|
||||||
var ns = false
|
|
||||||
|
|
||||||
var condNeedsSplit = false
|
var condNeedsSplit = false
|
||||||
n[0] = ctx.lowerStmtListExprs(n[0], condNeedsSplit)
|
n[0] = ctx.lowerStmtListExprs(n[0], condNeedsSplit)
|
||||||
var bodyNeedsSplit = false
|
var bodyNeedsSplit = false
|
||||||
|
|
|
||||||
|
|
@ -53,11 +53,10 @@ const
|
||||||
"Copyright (c) 2006-" & copyrightYear & " by Andreas Rumpf\n"
|
"Copyright (c) 2006-" & copyrightYear & " by Andreas Rumpf\n"
|
||||||
|
|
||||||
proc genFeatureDesc[T: enum](t: typedesc[T]): string {.compileTime.} =
|
proc genFeatureDesc[T: enum](t: typedesc[T]): string {.compileTime.} =
|
||||||
var x = ""
|
result = ""
|
||||||
for f in low(T)..high(T):
|
for f in T:
|
||||||
if x.len > 0: x.add "|"
|
if result.len > 0: result.add "|"
|
||||||
x.add $f
|
result.add $f
|
||||||
x
|
|
||||||
|
|
||||||
const
|
const
|
||||||
Usage = slurp"../doc/basicopt.txt".replace(" //", " ")
|
Usage = slurp"../doc/basicopt.txt".replace(" //", " ")
|
||||||
|
|
@ -146,24 +145,24 @@ proc splitSwitch(conf: ConfigRef; switch: string, cmd, arg: var string, pass: TC
|
||||||
proc processOnOffSwitch(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
|
proc processOnOffSwitch(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
|
||||||
info: TLineInfo) =
|
info: TLineInfo) =
|
||||||
case arg.normalize
|
case arg.normalize
|
||||||
of "","on": conf.options = conf.options + op
|
of "","on": conf.options.incl op
|
||||||
of "off": conf.options = conf.options - op
|
of "off": conf.options.excl op
|
||||||
else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
|
else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
|
||||||
|
|
||||||
proc processOnOffSwitchOrList(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
|
proc processOnOffSwitchOrList(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass,
|
||||||
info: TLineInfo): bool =
|
info: TLineInfo): bool =
|
||||||
result = false
|
result = false
|
||||||
case arg.normalize
|
case arg.normalize
|
||||||
of "on": conf.options = conf.options + op
|
of "on": conf.options.incl op
|
||||||
of "off": conf.options = conf.options - op
|
of "off": conf.options.excl op
|
||||||
of "list": result = true
|
of "list": result = true
|
||||||
else: localError(conf, info, errOnOffOrListExpectedButXFound % arg)
|
else: localError(conf, info, errOnOffOrListExpectedButXFound % arg)
|
||||||
|
|
||||||
proc processOnOffSwitchG(conf: ConfigRef; op: TGlobalOptions, arg: string, pass: TCmdLinePass,
|
proc processOnOffSwitchG(conf: ConfigRef; op: TGlobalOptions, arg: string, pass: TCmdLinePass,
|
||||||
info: TLineInfo) =
|
info: TLineInfo) =
|
||||||
case arg.normalize
|
case arg.normalize
|
||||||
of "", "on": conf.globalOptions = conf.globalOptions + op
|
of "", "on": conf.globalOptions.incl op
|
||||||
of "off": conf.globalOptions = conf.globalOptions - op
|
of "off": conf.globalOptions.excl op
|
||||||
else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
|
else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
|
||||||
|
|
||||||
proc expectArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
proc expectArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ proc initDefines*(symbols: StringTableRef) =
|
||||||
defineSymbol("nimMacrosSizealignof")
|
defineSymbol("nimMacrosSizealignof")
|
||||||
defineSymbol("nimNoZeroExtendMagic")
|
defineSymbol("nimNoZeroExtendMagic")
|
||||||
defineSymbol("nimMacrosGetNodeId")
|
defineSymbol("nimMacrosGetNodeId")
|
||||||
for f in low(Feature)..high(Feature):
|
for f in Feature:
|
||||||
defineSymbol("nimHas" & $f)
|
defineSymbol("nimHas" & $f)
|
||||||
|
|
||||||
for s in WarningsToStr:
|
for s in WarningsToStr:
|
||||||
|
|
|
||||||
|
|
@ -302,15 +302,13 @@ proc ropeFormatNamedVars(conf: ConfigRef; frmt: FormatStr,
|
||||||
|
|
||||||
proc genComment(d: PDoc, n: PNode): string =
|
proc genComment(d: PDoc, n: PNode): string =
|
||||||
result = ""
|
result = ""
|
||||||
var dummyHasToc: bool
|
|
||||||
if n.comment.len > 0:
|
if n.comment.len > 0:
|
||||||
var comment2 = n.comment
|
let comment = n.comment
|
||||||
when false:
|
when false:
|
||||||
# RFC: to preseve newlines in comments, this would work:
|
# RFC: to preseve newlines in comments, this would work:
|
||||||
comment2 = comment2.replace("\n", "\n\n")
|
comment = comment.replace("\n", "\n\n")
|
||||||
renderRstToOut(d[], parseRst(comment2, toFullPath(d.conf, n.info),
|
renderRstToOut(d[], parseRst(comment, toFullPath(d.conf, n.info), toLinenumber(n.info),
|
||||||
toLinenumber(n.info), toColumn(n.info),
|
toColumn(n.info), (var dummy: bool; dummy), d.options, d.conf), result)
|
||||||
dummyHasToc, d.options, d.conf), result)
|
|
||||||
|
|
||||||
proc genRecCommentAux(d: PDoc, n: PNode): Rope =
|
proc genRecCommentAux(d: PDoc, n: PNode): Rope =
|
||||||
if n == nil: return nil
|
if n == nil: return nil
|
||||||
|
|
@ -342,11 +340,10 @@ proc getPlainDocstring(n: PNode): string =
|
||||||
## You need to call this before genRecComment, whose side effects are removal
|
## You need to call this before genRecComment, whose side effects are removal
|
||||||
## of comments from the tree. The proc will recursively scan and return all
|
## of comments from the tree. The proc will recursively scan and return all
|
||||||
## the concatenated ``##`` comments of the node.
|
## the concatenated ``##`` comments of the node.
|
||||||
result = ""
|
if n == nil: result = ""
|
||||||
if n == nil: return
|
elif startsWith(n.comment, "##"):
|
||||||
if startsWith(n.comment, "##"):
|
|
||||||
result = n.comment
|
result = n.comment
|
||||||
if result.len < 1:
|
else:
|
||||||
for i in 0..<n.safeLen:
|
for i in 0..<n.safeLen:
|
||||||
result = getPlainDocstring(n[i])
|
result = getPlainDocstring(n[i])
|
||||||
if result.len > 0: return
|
if result.len > 0: return
|
||||||
|
|
@ -458,7 +455,6 @@ proc writeExample(d: PDoc; ex: PNode, rdoccmd: string) =
|
||||||
d.exampleGroups[rdoccmd].code.add "import r\"$1\"\n" % outp.string
|
d.exampleGroups[rdoccmd].code.add "import r\"$1\"\n" % outp.string
|
||||||
|
|
||||||
proc runAllExamples(d: PDoc) =
|
proc runAllExamples(d: PDoc) =
|
||||||
let backend = d.conf.backend
|
|
||||||
# This used to be: `let backend = if isDefined(d.conf, "js"): "js"` (etc), however
|
# This used to be: `let backend = if isDefined(d.conf, "js"): "js"` (etc), however
|
||||||
# using `-d:js` (etc) cannot work properly, eg would fail with `importjs`
|
# using `-d:js` (etc) cannot work properly, eg would fail with `importjs`
|
||||||
# since semantics are affected by `config.backend`, not by isDefined(d.conf, "js")
|
# since semantics are affected by `config.backend`, not by isDefined(d.conf, "js")
|
||||||
|
|
@ -522,20 +518,6 @@ proc prepareExample(d: PDoc; n: PNode): tuple[rdoccmd: string, code: string] =
|
||||||
for imp in imports: runnableExamples.add imp
|
for imp in imports: runnableExamples.add imp
|
||||||
runnableExamples.add newTree(nkBlockStmt, newNode(nkEmpty), copyTree savedLastSon)
|
runnableExamples.add newTree(nkBlockStmt, newNode(nkEmpty), copyTree savedLastSon)
|
||||||
|
|
||||||
proc renderNimCodeOld(d: PDoc, n: PNode, dest: var Rope) =
|
|
||||||
## this is a rather hacky way to get rid of the initial indentation
|
|
||||||
## that the renderer currently produces:
|
|
||||||
# deadcode
|
|
||||||
var i = 0
|
|
||||||
var body = n.lastSon
|
|
||||||
if body.len == 1 and body.kind == nkStmtList and
|
|
||||||
body.lastSon.kind == nkStmtList:
|
|
||||||
body = body.lastSon
|
|
||||||
for b in body:
|
|
||||||
if i > 0: dest.add "\n"
|
|
||||||
inc i
|
|
||||||
nodeToHighlightedHtml(d, b, dest, {renderRunnableExamples}, nil)
|
|
||||||
|
|
||||||
type RunnableState = enum
|
type RunnableState = enum
|
||||||
rsStart
|
rsStart
|
||||||
rsComment
|
rsComment
|
||||||
|
|
@ -575,12 +557,9 @@ proc getAllRunnableExamplesImpl(d: PDoc; n: PNode, dest: var Rope, state: Runnab
|
||||||
inc d.listingCounter
|
inc d.listingCounter
|
||||||
let id = $d.listingCounter
|
let id = $d.listingCounter
|
||||||
dest.add(d.config.getOrDefault"doc.listing_start" % [id, "langNim"])
|
dest.add(d.config.getOrDefault"doc.listing_start" % [id, "langNim"])
|
||||||
when true:
|
|
||||||
var dest2 = ""
|
var dest2 = ""
|
||||||
renderNimCode(dest2, code, isLatex = d.conf.cmd == cmdRst2tex)
|
renderNimCode(dest2, code, isLatex = d.conf.cmd == cmdRst2tex)
|
||||||
dest.add dest2
|
dest.add dest2
|
||||||
else:
|
|
||||||
renderNimCodeOld(d, n, dest)
|
|
||||||
dest.add(d.config.getOrDefault"doc.listing_end" % id)
|
dest.add(d.config.getOrDefault"doc.listing_end" % id)
|
||||||
return rsRunnable
|
return rsRunnable
|
||||||
else: discard
|
else: discard
|
||||||
|
|
@ -1213,12 +1192,12 @@ proc genOutFile(d: PDoc): Rope =
|
||||||
var tmp = ""
|
var tmp = ""
|
||||||
renderTocEntries(d[], j, 1, tmp)
|
renderTocEntries(d[], j, 1, tmp)
|
||||||
var toc = tmp.rope
|
var toc = tmp.rope
|
||||||
for i in low(TSymKind)..high(TSymKind):
|
for i in TSymKind:
|
||||||
genSection(d, i)
|
genSection(d, i)
|
||||||
toc.add(d.toc[i])
|
toc.add(d.toc[i])
|
||||||
if toc != nil:
|
if toc != nil:
|
||||||
toc = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.toc"), ["content"], [toc])
|
toc = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.toc"), ["content"], [toc])
|
||||||
for i in low(TSymKind)..high(TSymKind): code.add(d.section[i])
|
for i in TSymKind: code.add(d.section[i])
|
||||||
|
|
||||||
# Extract the title. Non API modules generate an entry in the index table.
|
# Extract the title. Non API modules generate an entry in the index table.
|
||||||
if d.meta[metaTitle].len != 0:
|
if d.meta[metaTitle].len != 0:
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,7 @@ proc setCC*(conf: ConfigRef; ccname: string; info: TLineInfo) =
|
||||||
conf.compileOptions = getConfigVar(conf, conf.cCompiler, ".options.always")
|
conf.compileOptions = getConfigVar(conf, conf.cCompiler, ".options.always")
|
||||||
conf.linkOptions = ""
|
conf.linkOptions = ""
|
||||||
conf.cCompilerPath = getConfigVar(conf, conf.cCompiler, ".path")
|
conf.cCompilerPath = getConfigVar(conf, conf.cCompiler, ".path")
|
||||||
for i in low(CC)..high(CC): undefSymbol(conf.symbols, CC[i].name)
|
for c in CC: undefSymbol(conf.symbols, c.name)
|
||||||
defineSymbol(conf.symbols, CC[conf.cCompiler].name)
|
defineSymbol(conf.symbols, CC[conf.cCompiler].name)
|
||||||
|
|
||||||
proc addOpt(dest: var string, src: string) =
|
proc addOpt(dest: var string, src: string) =
|
||||||
|
|
@ -353,7 +353,7 @@ proc addCompileOptionCmd*(conf: ConfigRef; option: string) =
|
||||||
|
|
||||||
proc initVars*(conf: ConfigRef) =
|
proc initVars*(conf: ConfigRef) =
|
||||||
# we need to define the symbol here, because ``CC`` may have never been set!
|
# we need to define the symbol here, because ``CC`` may have never been set!
|
||||||
for i in low(CC)..high(CC): undefSymbol(conf.symbols, CC[i].name)
|
for c in CC: undefSymbol(conf.symbols, c.name)
|
||||||
defineSymbol(conf.symbols, CC[conf.cCompiler].name)
|
defineSymbol(conf.symbols, CC[conf.cCompiler].name)
|
||||||
addCompileOption(conf, getConfigVar(conf, conf.cCompiler, ".options.always"))
|
addCompileOption(conf, getConfigVar(conf, conf.cCompiler, ".options.always"))
|
||||||
#addLinkOption(getConfigVar(cCompiler, ".options.linker"))
|
#addLinkOption(getConfigVar(cCompiler, ".options.linker"))
|
||||||
|
|
|
||||||
|
|
@ -199,8 +199,8 @@ proc parseLine(p: var TTmplParser) =
|
||||||
inc(j)
|
inc(j)
|
||||||
llStreamWrite(p.outp, "\\n\"")
|
llStreamWrite(p.outp, "\\n\"")
|
||||||
|
|
||||||
proc filterTmpl*(stdin: PLLStream, filename: AbsoluteFile,
|
proc filterTmpl*(conf: ConfigRef, stdin: PLLStream, filename: AbsoluteFile,
|
||||||
call: PNode; conf: ConfigRef): PLLStream =
|
call: PNode): PLLStream =
|
||||||
var p: TTmplParser
|
var p: TTmplParser
|
||||||
p.config = conf
|
p.config = conf
|
||||||
p.info = newLineInfo(conf, filename, 0, 0)
|
p.info = newLineInfo(conf, filename, 0, 0)
|
||||||
|
|
@ -214,9 +214,9 @@ proc filterTmpl*(stdin: PLLStream, filename: AbsoluteFile,
|
||||||
p.x = newStringOfCap(120)
|
p.x = newStringOfCap(120)
|
||||||
# do not process the first line which contains the directive:
|
# do not process the first line which contains the directive:
|
||||||
if llStreamReadLine(p.inp, p.x):
|
if llStreamReadLine(p.inp, p.x):
|
||||||
p.info.line = p.info.line + 1'u16
|
inc p.info.line
|
||||||
while llStreamReadLine(p.inp, p.x):
|
while llStreamReadLine(p.inp, p.x):
|
||||||
p.info.line = p.info.line + 1'u16
|
inc p.info.line
|
||||||
parseLine(p)
|
parseLine(p)
|
||||||
newLine(p)
|
newLine(p)
|
||||||
result = p.outp
|
result = p.outp
|
||||||
|
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
#
|
|
||||||
#
|
|
||||||
# The Nim Compiler
|
|
||||||
# (c) Copyright 2015 Andreas Rumpf
|
|
||||||
#
|
|
||||||
# See the file "copying.txt", included in this
|
|
||||||
# distribution, for details about the copyright.
|
|
||||||
#
|
|
||||||
|
|
||||||
## This module implements for loop detection for better C code generation.
|
|
||||||
|
|
||||||
import ast, astalgo
|
|
||||||
|
|
||||||
const
|
|
||||||
someCmp = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
|
|
||||||
mLeI, mLeF64, mLeU, mLeEnum,
|
|
||||||
mLeCh, mLeB, mLePtr, mLtI, mLtF64, mLtU, mLtEnum,
|
|
||||||
mLtCh, mLtB, mLtPtr}
|
|
||||||
|
|
||||||
proc isCounter(s: PSym): bool {.inline.} =
|
|
||||||
s.kind in {skResult, skVar, skLet, skTemp} and
|
|
||||||
{sfGlobal, sfAddrTaken} * s.flags == {}
|
|
||||||
|
|
||||||
proc isCall(n: PNode): bool {.inline.} =
|
|
||||||
n.kind in nkCallKinds and n[0].kind == nkSym
|
|
||||||
|
|
||||||
proc fromSystem(op: PSym): bool = sfSystemModule in getModule(op).flags
|
|
||||||
|
|
||||||
proc getCounter(lastStmt: PNode): PSym =
|
|
||||||
if lastStmt.isCall:
|
|
||||||
let op = lastStmt.sym
|
|
||||||
if op.magic in {mDec, mInc} or
|
|
||||||
((op.name.s == "+=" or op.name.s == "-=") and op.fromSystem):
|
|
||||||
if op[1].kind == nkSym and isCounter(op[1].sym):
|
|
||||||
result = op[1].sym
|
|
||||||
|
|
||||||
proc counterInTree(n, loop: PNode; counter: PSym): bool =
|
|
||||||
# prune the search tree: within the loop the counter may be used:
|
|
||||||
if n == loop: return
|
|
||||||
case n.kind
|
|
||||||
of nkSym:
|
|
||||||
if n.sym == counter: return true
|
|
||||||
of nkVarSection, nkLetSection:
|
|
||||||
# definitions are fine!
|
|
||||||
for it in n:
|
|
||||||
if counterInTree(it.lastSon): return true
|
|
||||||
else:
|
|
||||||
for i in 0..<n.safeLen:
|
|
||||||
if counterInTree(n[i], loop, counter): return true
|
|
||||||
|
|
||||||
proc copyExcept(n: PNode, x, dest: PNode) =
|
|
||||||
if x == n: return
|
|
||||||
if n.kind in {nkStmtList, nkStmtListExpr}:
|
|
||||||
for i in 0..<n.len: copyExcept(n[i], x, dest)
|
|
||||||
else:
|
|
||||||
dest.add n
|
|
||||||
|
|
||||||
type
|
|
||||||
ForLoop* = object
|
|
||||||
counter*: PSym
|
|
||||||
init*, cond*, increment*, body*: PNode
|
|
||||||
|
|
||||||
proc extractForLoop*(loop, fullTree: PNode): ForLoop =
|
|
||||||
## returns 'counter == nil' if the while loop 'n' is not a for loop:
|
|
||||||
assert loop.kind == nkWhileStmt
|
|
||||||
let cond == loop[0]
|
|
||||||
|
|
||||||
if not cond.isCall: return
|
|
||||||
if cond[0].sym.magic notin someCmp: return
|
|
||||||
|
|
||||||
var lastStmt = loop[1]
|
|
||||||
while lastStmt.kind in {nkStmtList, nkStmtListExpr}:
|
|
||||||
lastStmt = lastStmt.lastSon
|
|
||||||
|
|
||||||
let counter = getCounter(lastStmt)
|
|
||||||
if counter.isNil or counter.ast.isNil: return
|
|
||||||
|
|
||||||
template `=~`(a, b): expr = a.kind == nkSym and a.sym == b
|
|
||||||
|
|
||||||
if cond[1] =~ counter or cond[2] =~ counter:
|
|
||||||
# ok, now check 'counter' is not used *after* the loop
|
|
||||||
if counterInTree(fullTree, loop, counter): return
|
|
||||||
# ok, success, fill in the fields:
|
|
||||||
result.counter = counter
|
|
||||||
result.init = counter.ast
|
|
||||||
result.cond = cond
|
|
||||||
result.increment = lastStmt
|
|
||||||
result.body = newNodeI(nkStmtList, loop[1].info)
|
|
||||||
copyExcept(loop[1], lastStmt, result.body)
|
|
||||||
|
|
@ -91,7 +91,7 @@ proc isLastRead(location: PNode; cfg: ControlFlowGraph; otherRead: var PNode; pc
|
||||||
return -1
|
return -1
|
||||||
inc pc
|
inc pc
|
||||||
of goto:
|
of goto:
|
||||||
pc = pc + cfg[pc].dest
|
pc += cfg[pc].dest
|
||||||
of fork:
|
of fork:
|
||||||
# every branch must lead to the last read of the location:
|
# every branch must lead to the last read of the location:
|
||||||
var variantA = pc + 1
|
var variantA = pc + 1
|
||||||
|
|
@ -156,7 +156,7 @@ proc isFirstWrite(location: PNode; cfg: ControlFlowGraph; pc, until: int): int =
|
||||||
return -1
|
return -1
|
||||||
inc pc
|
inc pc
|
||||||
of goto:
|
of goto:
|
||||||
pc = pc + cfg[pc].dest
|
pc += cfg[pc].dest
|
||||||
of fork:
|
of fork:
|
||||||
# every branch must not contain a def/use of our location:
|
# every branch must not contain a def/use of our location:
|
||||||
var variantA = pc + 1
|
var variantA = pc + 1
|
||||||
|
|
@ -198,7 +198,7 @@ proc initialized(code: ControlFlowGraph; pc: int,
|
||||||
while pc < code.len:
|
while pc < code.len:
|
||||||
case code[pc].kind
|
case code[pc].kind
|
||||||
of goto:
|
of goto:
|
||||||
pc = pc + code[pc].dest
|
pc += code[pc].dest
|
||||||
of fork:
|
of fork:
|
||||||
var initA = initIntSet()
|
var initA = initIntSet()
|
||||||
var initB = initIntSet()
|
var initB = initIntSet()
|
||||||
|
|
|
||||||
|
|
@ -373,8 +373,8 @@ proc `*`*(lhs,rhs: Int128): Int128 =
|
||||||
let b00 = cast[uint64](rhs.udata[0])
|
let b00 = cast[uint64](rhs.udata[0])
|
||||||
|
|
||||||
result = makeInt128(high64(lhs) * low64(rhs) + low64(lhs) * high64(rhs) + a32 * b32, a00 * b00)
|
result = makeInt128(high64(lhs) * low64(rhs) + low64(lhs) * high64(rhs) + a32 * b32, a00 * b00)
|
||||||
result = result + toInt128(a32 * b00) shl 32
|
result += toInt128(a32 * b00) shl 32
|
||||||
result = result + toInt128(a00 * b32) shl 32
|
result += toInt128(a00 * b32) shl 32
|
||||||
|
|
||||||
proc `*=`*(a: var Int128, b: Int128) =
|
proc `*=`*(a: var Int128, b: Int128) =
|
||||||
a = a * b
|
a = a * b
|
||||||
|
|
@ -427,7 +427,7 @@ proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
|
||||||
for i in 0..shift:
|
for i in 0..shift:
|
||||||
quotient = quotient shl 1
|
quotient = quotient shl 1
|
||||||
if dividend >= denominator:
|
if dividend >= denominator:
|
||||||
dividend = dividend - denominator
|
dividend -= denominator
|
||||||
quotient = bitor(quotient, One)
|
quotient = bitor(quotient, One)
|
||||||
|
|
||||||
denominator = denominator shr 1
|
denominator = denominator shr 1
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ type
|
||||||
Emitter* = object
|
Emitter* = object
|
||||||
config: ConfigRef
|
config: ConfigRef
|
||||||
fid: FileIndex
|
fid: FileIndex
|
||||||
lastTok: TTokType
|
lastTok: TokType
|
||||||
inquote, lastTokWasTerse: bool
|
inquote, lastTokWasTerse: bool
|
||||||
semicolons: SemicolonKind
|
semicolons: SemicolonKind
|
||||||
col, lastLineNumber, lineSpan, indentLevel, indWidth*, inSection: int
|
col, lastLineNumber, lineSpan, indentLevel, indWidth*, inSection: int
|
||||||
|
|
@ -402,7 +402,7 @@ proc endsInAlpha(em: Emitter): bool =
|
||||||
while i >= 0 and em.kinds[i] in {ltBeginSection, ltEndSection}: dec(i)
|
while i >= 0 and em.kinds[i] in {ltBeginSection, ltEndSection}: dec(i)
|
||||||
result = if i >= 0: em.tokens[i].lastChar in SymChars+{'_'} else: false
|
result = if i >= 0: em.tokens[i].lastChar in SymChars+{'_'} else: false
|
||||||
|
|
||||||
proc emitComment(em: var Emitter; tok: TToken; dontIndent: bool) =
|
proc emitComment(em: var Emitter; tok: Token; dontIndent: bool) =
|
||||||
var col = em.col
|
var col = em.col
|
||||||
let lit = strip fileSection(em.config, em.fid, tok.commentOffsetA, tok.commentOffsetB)
|
let lit = strip fileSection(em.config, em.fid, tok.commentOffsetA, tok.commentOffsetB)
|
||||||
em.lineSpan = countNewlines(lit)
|
em.lineSpan = countNewlines(lit)
|
||||||
|
|
@ -417,7 +417,7 @@ proc emitComment(em: var Emitter; tok: TToken; dontIndent: bool) =
|
||||||
inc col
|
inc col
|
||||||
emitMultilineComment(em, lit, col, dontIndent)
|
emitMultilineComment(em, lit, col, dontIndent)
|
||||||
|
|
||||||
proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
|
proc emitTok*(em: var Emitter; L: Lexer; tok: Token) =
|
||||||
template wasExportMarker(em): bool =
|
template wasExportMarker(em): bool =
|
||||||
em.kinds.len > 0 and em.kinds[^1] == ltExportMarker
|
em.kinds.len > 0 and em.kinds[^1] == ltExportMarker
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ const
|
||||||
# don't forget to update the 'highlite' module if these charsets should change
|
# don't forget to update the 'highlite' module if these charsets should change
|
||||||
|
|
||||||
type
|
type
|
||||||
TTokType* = enum
|
TokType* = enum
|
||||||
tkInvalid, tkEof, # order is important here!
|
tkInvalid, tkEof, # order is important here!
|
||||||
tkSymbol, # keywords:
|
tkSymbol, # keywords:
|
||||||
tkAddr, tkAnd, tkAs, tkAsm,
|
tkAddr, tkAnd, tkAs, tkAsm,
|
||||||
|
|
@ -64,7 +64,7 @@ type
|
||||||
tkOpr, tkComment, tkAccent,
|
tkOpr, tkComment, tkAccent,
|
||||||
tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr
|
tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr
|
||||||
|
|
||||||
TTokTypes* = set[TTokType]
|
TokTypes* = set[TokType]
|
||||||
|
|
||||||
const
|
const
|
||||||
weakTokens = {tkComma, tkSemiColon, tkColon,
|
weakTokens = {tkComma, tkSemiColon, tkColon,
|
||||||
|
|
@ -73,7 +73,7 @@ const
|
||||||
# tokens that should not be considered for previousToken
|
# tokens that should not be considered for previousToken
|
||||||
tokKeywordLow* = succ(tkSymbol)
|
tokKeywordLow* = succ(tkSymbol)
|
||||||
tokKeywordHigh* = pred(tkIntLit)
|
tokKeywordHigh* = pred(tkIntLit)
|
||||||
TokTypeToStr*: array[TTokType, string] = ["tkInvalid", "[EOF]",
|
TokTypeToStr*: array[TokType, string] = ["tkInvalid", "[EOF]",
|
||||||
"tkSymbol",
|
"tkSymbol",
|
||||||
"addr", "and", "as", "asm",
|
"addr", "and", "as", "asm",
|
||||||
"bind", "block", "break", "case", "cast",
|
"bind", "block", "break", "case", "cast",
|
||||||
|
|
@ -104,22 +104,19 @@ const
|
||||||
"tkPrefixOpr", "tkPostfixOpr"]
|
"tkPrefixOpr", "tkPostfixOpr"]
|
||||||
|
|
||||||
type
|
type
|
||||||
TNumericalBase* = enum
|
NumericalBase* = enum
|
||||||
base10, # base10 is listed as the first element,
|
base10, # base10 is listed as the first element,
|
||||||
# so that it is the correct default value
|
# so that it is the correct default value
|
||||||
base2, base8, base16
|
base2, base8, base16
|
||||||
|
|
||||||
CursorPosition* {.pure.} = enum ## XXX remove this again
|
Token* = object # a Nim token
|
||||||
None, InToken, BeforeToken, AfterToken
|
tokType*: TokType # the type of the token
|
||||||
|
|
||||||
TToken* = object # a Nim token
|
|
||||||
tokType*: TTokType # the type of the token
|
|
||||||
indent*: int # the indentation; != -1 if the token has been
|
indent*: int # the indentation; != -1 if the token has been
|
||||||
# preceded with indentation
|
# preceded with indentation
|
||||||
ident*: PIdent # the parsed identifier
|
ident*: PIdent # the parsed identifier
|
||||||
iNumber*: BiggestInt # the parsed integer literal
|
iNumber*: BiggestInt # the parsed integer literal
|
||||||
fNumber*: BiggestFloat # the parsed floating point literal
|
fNumber*: BiggestFloat # the parsed floating point literal
|
||||||
base*: TNumericalBase # the numerical base; only valid for int
|
base*: NumericalBase # the numerical base; only valid for int
|
||||||
# or float literals
|
# or float literals
|
||||||
strongSpaceA*: int8 # leading spaces of an operator
|
strongSpaceA*: int8 # leading spaces of an operator
|
||||||
strongSpaceB*: int8 # trailing spaces of an operator
|
strongSpaceB*: int8 # trailing spaces of an operator
|
||||||
|
|
@ -131,22 +128,21 @@ type
|
||||||
# like 0b01 or r"\L" are unaffected
|
# like 0b01 or r"\L" are unaffected
|
||||||
commentOffsetA*, commentOffsetB*: int
|
commentOffsetA*, commentOffsetB*: int
|
||||||
|
|
||||||
TErrorHandler* = proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string)
|
ErrorHandler* = proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string)
|
||||||
TLexer* = object of TBaseLexer
|
Lexer* = object of TBaseLexer
|
||||||
fileIdx*: FileIndex
|
fileIdx*: FileIndex
|
||||||
indentAhead*: int # if > 0 an indentation has already been read
|
indentAhead*: int # if > 0 an indentation has already been read
|
||||||
# this is needed because scanning comments
|
# this is needed because scanning comments
|
||||||
# needs so much look-ahead
|
# needs so much look-ahead
|
||||||
currLineIndent*: int
|
currLineIndent*: int
|
||||||
strongSpaces*, allowTabs*: bool
|
strongSpaces*, allowTabs*: bool
|
||||||
cursor*: CursorPosition
|
errorHandler*: ErrorHandler
|
||||||
errorHandler*: TErrorHandler
|
|
||||||
cache*: IdentCache
|
cache*: IdentCache
|
||||||
when defined(nimsuggest):
|
when defined(nimsuggest):
|
||||||
previousToken: TLineInfo
|
previousToken: TLineInfo
|
||||||
config*: ConfigRef
|
config*: ConfigRef
|
||||||
|
|
||||||
proc getLineInfo*(L: TLexer, tok: TToken): TLineInfo {.inline.} =
|
proc getLineInfo*(L: Lexer, tok: Token): TLineInfo {.inline.} =
|
||||||
result = newLineInfo(L.fileIdx, tok.line, tok.col)
|
result = newLineInfo(L.fileIdx, tok.line, tok.col)
|
||||||
when defined(nimpretty):
|
when defined(nimpretty):
|
||||||
result.offsetA = tok.offsetA
|
result.offsetA = tok.offsetA
|
||||||
|
|
@ -154,8 +150,8 @@ proc getLineInfo*(L: TLexer, tok: TToken): TLineInfo {.inline.} =
|
||||||
result.commentOffsetA = tok.commentOffsetA
|
result.commentOffsetA = tok.commentOffsetA
|
||||||
result.commentOffsetB = tok.commentOffsetB
|
result.commentOffsetB = tok.commentOffsetB
|
||||||
|
|
||||||
proc isKeyword*(kind: TTokType): bool =
|
proc isKeyword*(kind: TokType): bool =
|
||||||
result = (kind >= tokKeywordLow) and (kind <= tokKeywordHigh)
|
(kind >= tokKeywordLow) and (kind <= tokKeywordHigh)
|
||||||
|
|
||||||
template ones(n): untyped = ((1 shl n)-1) # for utf-8 conversion
|
template ones(n): untyped = ((1 shl n)-1) # for utf-8 conversion
|
||||||
|
|
||||||
|
|
@ -169,28 +165,27 @@ proc isNimIdentifier*(s: string): bool =
|
||||||
inc(i)
|
inc(i)
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc `$`*(tok: TToken): string =
|
proc `$`*(tok: Token): string =
|
||||||
case tok.tokType
|
case tok.tokType
|
||||||
of tkIntLit..tkInt64Lit: result = $tok.iNumber
|
of tkIntLit..tkInt64Lit: $tok.iNumber
|
||||||
of tkFloatLit..tkFloat64Lit: result = $tok.fNumber
|
of tkFloatLit..tkFloat64Lit: $tok.fNumber
|
||||||
of tkInvalid, tkStrLit..tkCharLit, tkComment: result = tok.literal
|
of tkInvalid, tkStrLit..tkCharLit, tkComment: tok.literal
|
||||||
of tkParLe..tkColon, tkEof, tkAccent:
|
of tkParLe..tkColon, tkEof, tkAccent: TokTypeToStr[tok.tokType]
|
||||||
result = TokTypeToStr[tok.tokType]
|
|
||||||
else:
|
else:
|
||||||
if tok.ident != nil:
|
if tok.ident != nil:
|
||||||
result = tok.ident.s
|
tok.ident.s
|
||||||
else:
|
else:
|
||||||
result = ""
|
""
|
||||||
|
|
||||||
proc prettyTok*(tok: TToken): string =
|
proc prettyTok*(tok: Token): string =
|
||||||
if isKeyword(tok.tokType): result = "keyword " & tok.ident.s
|
if isKeyword(tok.tokType): "keyword " & tok.ident.s
|
||||||
else: result = $tok
|
else: $tok
|
||||||
|
|
||||||
proc printTok*(conf: ConfigRef; tok: TToken) =
|
proc printTok*(conf: ConfigRef; tok: Token) =
|
||||||
msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" &
|
msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" &
|
||||||
TokTypeToStr[tok.tokType] & " " & $tok)
|
TokTypeToStr[tok.tokType] & " " & $tok)
|
||||||
|
|
||||||
proc initToken*(L: var TToken) =
|
proc initToken*(L: var Token) =
|
||||||
L.tokType = tkInvalid
|
L.tokType = tkInvalid
|
||||||
L.iNumber = 0
|
L.iNumber = 0
|
||||||
L.indent = 0
|
L.indent = 0
|
||||||
|
|
@ -203,7 +198,7 @@ proc initToken*(L: var TToken) =
|
||||||
L.commentOffsetA = 0
|
L.commentOffsetA = 0
|
||||||
L.commentOffsetB = 0
|
L.commentOffsetB = 0
|
||||||
|
|
||||||
proc fillToken(L: var TToken) =
|
proc fillToken(L: var Token) =
|
||||||
L.tokType = tkInvalid
|
L.tokType = tkInvalid
|
||||||
L.iNumber = 0
|
L.iNumber = 0
|
||||||
L.indent = 0
|
L.indent = 0
|
||||||
|
|
@ -216,7 +211,7 @@ proc fillToken(L: var TToken) =
|
||||||
L.commentOffsetA = 0
|
L.commentOffsetA = 0
|
||||||
L.commentOffsetB = 0
|
L.commentOffsetB = 0
|
||||||
|
|
||||||
proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream;
|
proc openLexer*(lex: var Lexer, fileIdx: FileIndex, inputstream: PLLStream;
|
||||||
cache: IdentCache; config: ConfigRef) =
|
cache: IdentCache; config: ConfigRef) =
|
||||||
openBaseLexer(lex, inputstream)
|
openBaseLexer(lex, inputstream)
|
||||||
lex.fileIdx = fileIdx
|
lex.fileIdx = fileIdx
|
||||||
|
|
@ -228,36 +223,36 @@ proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream;
|
||||||
lex.previousToken.fileIndex = fileIdx
|
lex.previousToken.fileIndex = fileIdx
|
||||||
lex.config = config
|
lex.config = config
|
||||||
|
|
||||||
proc openLexer*(lex: var TLexer, filename: AbsoluteFile, inputstream: PLLStream;
|
proc openLexer*(lex: var Lexer, filename: AbsoluteFile, inputstream: PLLStream;
|
||||||
cache: IdentCache; config: ConfigRef) =
|
cache: IdentCache; config: ConfigRef) =
|
||||||
openLexer(lex, fileInfoIdx(config, filename), inputstream, cache, config)
|
openLexer(lex, fileInfoIdx(config, filename), inputstream, cache, config)
|
||||||
|
|
||||||
proc closeLexer*(lex: var TLexer) =
|
proc closeLexer*(lex: var Lexer) =
|
||||||
if lex.config != nil:
|
if lex.config != nil:
|
||||||
inc(lex.config.linesCompiled, lex.lineNumber)
|
inc(lex.config.linesCompiled, lex.lineNumber)
|
||||||
closeBaseLexer(lex)
|
closeBaseLexer(lex)
|
||||||
|
|
||||||
proc getLineInfo(L: TLexer): TLineInfo =
|
proc getLineInfo(L: Lexer): TLineInfo =
|
||||||
result = newLineInfo(L.fileIdx, L.lineNumber, getColNumber(L, L.bufpos))
|
result = newLineInfo(L.fileIdx, L.lineNumber, getColNumber(L, L.bufpos))
|
||||||
|
|
||||||
proc dispMessage(L: TLexer; info: TLineInfo; msg: TMsgKind; arg: string) =
|
proc dispMessage(L: Lexer; info: TLineInfo; msg: TMsgKind; arg: string) =
|
||||||
if L.errorHandler.isNil:
|
if L.errorHandler.isNil:
|
||||||
msgs.message(L.config, info, msg, arg)
|
msgs.message(L.config, info, msg, arg)
|
||||||
else:
|
else:
|
||||||
L.errorHandler(L.config, info, msg, arg)
|
L.errorHandler(L.config, info, msg, arg)
|
||||||
|
|
||||||
proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") =
|
proc lexMessage*(L: Lexer, msg: TMsgKind, arg = "") =
|
||||||
L.dispMessage(getLineInfo(L), msg, arg)
|
L.dispMessage(getLineInfo(L), msg, arg)
|
||||||
|
|
||||||
proc lexMessageTok*(L: TLexer, msg: TMsgKind, tok: TToken, arg = "") =
|
proc lexMessageTok*(L: Lexer, msg: TMsgKind, tok: Token, arg = "") =
|
||||||
var info = newLineInfo(L.fileIdx, tok.line, tok.col)
|
var info = newLineInfo(L.fileIdx, tok.line, tok.col)
|
||||||
L.dispMessage(info, msg, arg)
|
L.dispMessage(info, msg, arg)
|
||||||
|
|
||||||
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
|
proc lexMessagePos(L: var Lexer, msg: TMsgKind, pos: int, arg = "") =
|
||||||
var info = newLineInfo(L.fileIdx, L.lineNumber, pos - L.lineStart)
|
var info = newLineInfo(L.fileIdx, L.lineNumber, pos - L.lineStart)
|
||||||
L.dispMessage(info, msg, arg)
|
L.dispMessage(info, msg, arg)
|
||||||
|
|
||||||
proc matchTwoChars(L: TLexer, first: char, second: set[char]): bool =
|
proc matchTwoChars(L: Lexer, first: char, second: set[char]): bool =
|
||||||
result = (L.buf[L.bufpos] == first) and (L.buf[L.bufpos + 1] in second)
|
result = (L.buf[L.bufpos] == first) and (L.buf[L.bufpos + 1] in second)
|
||||||
|
|
||||||
template tokenBegin(tok, pos) {.dirty.} =
|
template tokenBegin(tok, pos) {.dirty.} =
|
||||||
|
|
@ -271,7 +266,6 @@ template tokenEnd(tok, pos) {.dirty.} =
|
||||||
let colB = getColNumber(L, pos)+1
|
let colB = getColNumber(L, pos)+1
|
||||||
if L.fileIdx == L.config.m.trackPos.fileIndex and L.config.m.trackPos.col in colA..colB and
|
if L.fileIdx == L.config.m.trackPos.fileIndex and L.config.m.trackPos.col in colA..colB and
|
||||||
L.lineNumber == L.config.m.trackPos.line.int and L.config.ideCmd in {ideSug, ideCon}:
|
L.lineNumber == L.config.m.trackPos.line.int and L.config.ideCmd in {ideSug, ideCon}:
|
||||||
L.cursor = CursorPosition.InToken
|
|
||||||
L.config.m.trackPos.col = colA.int16
|
L.config.m.trackPos.col = colA.int16
|
||||||
colA = 0
|
colA = 0
|
||||||
when defined(nimpretty):
|
when defined(nimpretty):
|
||||||
|
|
@ -296,23 +290,22 @@ template tokenEndPrevious(tok, pos) =
|
||||||
let colB = getColNumber(L, pos)
|
let colB = getColNumber(L, pos)
|
||||||
if L.fileIdx == L.config.m.trackPos.fileIndex and L.config.m.trackPos.col in colA..colB and
|
if L.fileIdx == L.config.m.trackPos.fileIndex and L.config.m.trackPos.col in colA..colB and
|
||||||
L.lineNumber == L.config.m.trackPos.line.int and L.config.ideCmd in {ideSug, ideCon}:
|
L.lineNumber == L.config.m.trackPos.line.int and L.config.ideCmd in {ideSug, ideCon}:
|
||||||
L.cursor = CursorPosition.BeforeToken
|
|
||||||
L.config.m.trackPos = L.previousToken
|
L.config.m.trackPos = L.previousToken
|
||||||
L.config.m.trackPosAttached = true
|
L.config.m.trackPosAttached = true
|
||||||
colA = 0
|
colA = 0
|
||||||
when defined(nimpretty):
|
when defined(nimpretty):
|
||||||
tok.offsetB = L.offsetBase + pos
|
tok.offsetB = L.offsetBase + pos
|
||||||
|
|
||||||
template eatChar(L: var TLexer, t: var TToken, replacementChar: char) =
|
template eatChar(L: var Lexer, t: var Token, replacementChar: char) =
|
||||||
t.literal.add(replacementChar)
|
t.literal.add(replacementChar)
|
||||||
inc(L.bufpos)
|
inc(L.bufpos)
|
||||||
|
|
||||||
template eatChar(L: var TLexer, t: var TToken) =
|
template eatChar(L: var Lexer, t: var Token) =
|
||||||
t.literal.add(L.buf[L.bufpos])
|
t.literal.add(L.buf[L.bufpos])
|
||||||
inc(L.bufpos)
|
inc(L.bufpos)
|
||||||
|
|
||||||
proc getNumber(L: var TLexer, result: var TToken) =
|
proc getNumber(L: var Lexer, result: var Token) =
|
||||||
proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: set[char]): Natural =
|
proc matchUnderscoreChars(L: var Lexer, tok: var Token, chars: set[char]): Natural =
|
||||||
var pos = L.bufpos # use registers for pos, buf
|
var pos = L.bufpos # use registers for pos, buf
|
||||||
result = 0
|
result = 0
|
||||||
while true:
|
while true:
|
||||||
|
|
@ -332,19 +325,19 @@ proc getNumber(L: var TLexer, result: var TToken) =
|
||||||
inc(pos)
|
inc(pos)
|
||||||
L.bufpos = pos
|
L.bufpos = pos
|
||||||
|
|
||||||
proc matchChars(L: var TLexer, tok: var TToken, chars: set[char]) =
|
proc matchChars(L: var Lexer, tok: var Token, chars: set[char]) =
|
||||||
var pos = L.bufpos # use registers for pos, buf
|
var pos = L.bufpos # use registers for pos, buf
|
||||||
while L.buf[pos] in chars:
|
while L.buf[pos] in chars:
|
||||||
tok.literal.add(L.buf[pos])
|
tok.literal.add(L.buf[pos])
|
||||||
inc(pos)
|
inc(pos)
|
||||||
L.bufpos = pos
|
L.bufpos = pos
|
||||||
|
|
||||||
proc lexMessageLitNum(L: var TLexer, msg: string, startpos: int, msgKind = errGenerated) =
|
proc lexMessageLitNum(L: var Lexer, msg: string, startpos: int, msgKind = errGenerated) =
|
||||||
# Used to get slightly human friendlier err messages.
|
# Used to get slightly human friendlier err messages.
|
||||||
const literalishChars = {'A'..'F', 'a'..'f', '0'..'9', 'X', 'x', 'o', 'O',
|
const literalishChars = {'A'..'F', 'a'..'f', '0'..'9', 'X', 'x', 'o', 'O',
|
||||||
'c', 'C', 'b', 'B', '_', '.', '\'', 'd', 'i', 'u'}
|
'c', 'C', 'b', 'B', '_', '.', '\'', 'd', 'i', 'u'}
|
||||||
var msgPos = L.bufpos
|
var msgPos = L.bufpos
|
||||||
var t: TToken
|
var t: Token
|
||||||
t.literal = ""
|
t.literal = ""
|
||||||
L.bufpos = startpos # Use L.bufpos as pos because of matchChars
|
L.bufpos = startpos # Use L.bufpos as pos because of matchChars
|
||||||
matchChars(L, t, literalishChars)
|
matchChars(L, t, literalishChars)
|
||||||
|
|
@ -612,7 +605,7 @@ proc getNumber(L: var TLexer, result: var TToken) =
|
||||||
tokenEnd(result, postPos-1)
|
tokenEnd(result, postPos-1)
|
||||||
L.bufpos = postPos
|
L.bufpos = postPos
|
||||||
|
|
||||||
proc handleHexChar(L: var TLexer, xi: var int; position: range[0..4]) =
|
proc handleHexChar(L: var Lexer, xi: var int; position: range[0..4]) =
|
||||||
template invalid() =
|
template invalid() =
|
||||||
lexMessage(L, errGenerated,
|
lexMessage(L, errGenerated,
|
||||||
"expected a hex digit, but found: " & L.buf[L.bufpos] &
|
"expected a hex digit, but found: " & L.buf[L.bufpos] &
|
||||||
|
|
@ -637,7 +630,7 @@ proc handleHexChar(L: var TLexer, xi: var int; position: range[0..4]) =
|
||||||
# Need to progress for `nim check`
|
# Need to progress for `nim check`
|
||||||
inc(L.bufpos)
|
inc(L.bufpos)
|
||||||
|
|
||||||
proc handleDecChars(L: var TLexer, xi: var int) =
|
proc handleDecChars(L: var Lexer, xi: var int) =
|
||||||
while L.buf[L.bufpos] in {'0'..'9'}:
|
while L.buf[L.bufpos] in {'0'..'9'}:
|
||||||
xi = (xi * 10) + (ord(L.buf[L.bufpos]) - ord('0'))
|
xi = (xi * 10) + (ord(L.buf[L.bufpos]) - ord('0'))
|
||||||
inc(L.bufpos)
|
inc(L.bufpos)
|
||||||
|
|
@ -680,7 +673,7 @@ proc addUnicodeCodePoint(s: var string, i: int) =
|
||||||
s[pos+4] = chr(i shr 6 and ones(6) or 0b10_0000_00)
|
s[pos+4] = chr(i shr 6 and ones(6) or 0b10_0000_00)
|
||||||
s[pos+5] = chr(i and ones(6) or 0b10_0000_00)
|
s[pos+5] = chr(i and ones(6) or 0b10_0000_00)
|
||||||
|
|
||||||
proc getEscapedChar(L: var TLexer, tok: var TToken) =
|
proc getEscapedChar(L: var Lexer, tok: var Token) =
|
||||||
inc(L.bufpos) # skip '\'
|
inc(L.bufpos) # skip '\'
|
||||||
case L.buf[L.bufpos]
|
case L.buf[L.bufpos]
|
||||||
of 'n', 'N':
|
of 'n', 'N':
|
||||||
|
|
@ -760,13 +753,7 @@ proc getEscapedChar(L: var TLexer, tok: var TToken) =
|
||||||
else: lexMessage(L, errGenerated, "invalid character constant")
|
else: lexMessage(L, errGenerated, "invalid character constant")
|
||||||
else: lexMessage(L, errGenerated, "invalid character constant")
|
else: lexMessage(L, errGenerated, "invalid character constant")
|
||||||
|
|
||||||
proc newString(s: cstring, len: int): string =
|
proc handleCRLF(L: var Lexer, pos: int): int =
|
||||||
## XXX, how come there is no support for this?
|
|
||||||
result = newString(len)
|
|
||||||
for i in 0..<len:
|
|
||||||
result[i] = s[i]
|
|
||||||
|
|
||||||
proc handleCRLF(L: var TLexer, pos: int): int =
|
|
||||||
template registerLine =
|
template registerLine =
|
||||||
let col = L.getColNumber(pos)
|
let col = L.getColNumber(pos)
|
||||||
|
|
||||||
|
|
@ -788,7 +775,7 @@ type
|
||||||
raw,
|
raw,
|
||||||
generalized
|
generalized
|
||||||
|
|
||||||
proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
|
proc getString(L: var Lexer, tok: var Token, mode: StringMode) =
|
||||||
var pos = L.bufpos
|
var pos = L.bufpos
|
||||||
var line = L.lineNumber # save linenumber for better error message
|
var line = L.lineNumber # save linenumber for better error message
|
||||||
tokenBegin(tok, pos - ord(mode == raw))
|
tokenBegin(tok, pos - ord(mode == raw))
|
||||||
|
|
@ -854,7 +841,7 @@ proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
|
||||||
inc(pos)
|
inc(pos)
|
||||||
L.bufpos = pos
|
L.bufpos = pos
|
||||||
|
|
||||||
proc getCharacter(L: var TLexer, tok: var TToken) =
|
proc getCharacter(L: var Lexer, tok: var Token) =
|
||||||
tokenBegin(tok, L.bufpos)
|
tokenBegin(tok, L.bufpos)
|
||||||
inc(L.bufpos) # skip '
|
inc(L.bufpos) # skip '
|
||||||
var c = L.buf[L.bufpos]
|
var c = L.buf[L.bufpos]
|
||||||
|
|
@ -871,7 +858,7 @@ proc getCharacter(L: var TLexer, tok: var TToken) =
|
||||||
tokenEndIgnore(tok, L.bufpos)
|
tokenEndIgnore(tok, L.bufpos)
|
||||||
inc(L.bufpos) # skip '
|
inc(L.bufpos) # skip '
|
||||||
|
|
||||||
proc getSymbol(L: var TLexer, tok: var TToken) =
|
proc getSymbol(L: var Lexer, tok: var Token) =
|
||||||
var h: Hash = 0
|
var h: Hash = 0
|
||||||
var pos = L.bufpos
|
var pos = L.bufpos
|
||||||
tokenBegin(tok, pos)
|
tokenBegin(tok, pos)
|
||||||
|
|
@ -901,21 +888,21 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
|
||||||
(tok.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)):
|
(tok.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)):
|
||||||
tok.tokType = tkSymbol
|
tok.tokType = tkSymbol
|
||||||
else:
|
else:
|
||||||
tok.tokType = TTokType(tok.ident.id + ord(tkSymbol))
|
tok.tokType = TokType(tok.ident.id + ord(tkSymbol))
|
||||||
if suspicious and {optStyleHint, optStyleError} * L.config.globalOptions != {}:
|
if suspicious and {optStyleHint, optStyleError} * L.config.globalOptions != {}:
|
||||||
lintReport(L.config, getLineInfo(L), tok.ident.s.normalize, tok.ident.s)
|
lintReport(L.config, getLineInfo(L), tok.ident.s.normalize, tok.ident.s)
|
||||||
L.bufpos = pos
|
L.bufpos = pos
|
||||||
|
|
||||||
|
|
||||||
proc endOperator(L: var TLexer, tok: var TToken, pos: int,
|
proc endOperator(L: var Lexer, tok: var Token, pos: int,
|
||||||
hash: Hash) {.inline.} =
|
hash: Hash) {.inline.} =
|
||||||
var h = !$hash
|
var h = !$hash
|
||||||
tok.ident = L.cache.getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
|
tok.ident = L.cache.getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
|
||||||
if (tok.ident.id < oprLow) or (tok.ident.id > oprHigh): tok.tokType = tkOpr
|
if (tok.ident.id < oprLow) or (tok.ident.id > oprHigh): tok.tokType = tkOpr
|
||||||
else: tok.tokType = TTokType(tok.ident.id - oprLow + ord(tkColon))
|
else: tok.tokType = TokType(tok.ident.id - oprLow + ord(tkColon))
|
||||||
L.bufpos = pos
|
L.bufpos = pos
|
||||||
|
|
||||||
proc getOperator(L: var TLexer, tok: var TToken) =
|
proc getOperator(L: var Lexer, tok: var Token) =
|
||||||
var pos = L.bufpos
|
var pos = L.bufpos
|
||||||
tokenBegin(tok, pos)
|
tokenBegin(tok, pos)
|
||||||
var h: Hash = 0
|
var h: Hash = 0
|
||||||
|
|
@ -935,18 +922,15 @@ proc getOperator(L: var TLexer, tok: var TToken) =
|
||||||
if L.buf[pos] in {CR, LF, nimlexbase.EndOfFile}:
|
if L.buf[pos] in {CR, LF, nimlexbase.EndOfFile}:
|
||||||
tok.strongSpaceB = -1
|
tok.strongSpaceB = -1
|
||||||
|
|
||||||
proc getPrecedence*(tok: TToken, strongSpaces: bool): int =
|
proc getPrecedence*(tok: Token): int =
|
||||||
## Calculates the precedence of the given token.
|
## Calculates the precedence of the given token.
|
||||||
template considerStrongSpaces(x): untyped =
|
|
||||||
x + (if strongSpaces: 100 - tok.strongSpaceA.int*10 else: 0)
|
|
||||||
|
|
||||||
case tok.tokType
|
case tok.tokType
|
||||||
of tkOpr:
|
of tkOpr:
|
||||||
let relevantChar = tok.ident.s[0]
|
let relevantChar = tok.ident.s[0]
|
||||||
|
|
||||||
# arrow like?
|
# arrow like?
|
||||||
if tok.ident.s.len > 1 and tok.ident.s[^1] == '>' and
|
if tok.ident.s.len > 1 and tok.ident.s[^1] == '>' and
|
||||||
tok.ident.s[^2] in {'-', '~', '='}: return considerStrongSpaces(1)
|
tok.ident.s[^2] in {'-', '~', '='}: return 1
|
||||||
|
|
||||||
template considerAsgn(value: untyped) =
|
template considerAsgn(value: untyped) =
|
||||||
result = if tok.ident.s[^1] == '=': 1 else: value
|
result = if tok.ident.s[^1] == '=': 1 else: value
|
||||||
|
|
@ -962,15 +946,13 @@ proc getPrecedence*(tok: TToken, strongSpaces: bool): int =
|
||||||
of '?': result = 2
|
of '?': result = 2
|
||||||
else: considerAsgn(2)
|
else: considerAsgn(2)
|
||||||
of tkDiv, tkMod, tkShl, tkShr: result = 9
|
of tkDiv, tkMod, tkShl, tkShr: result = 9
|
||||||
of tkIn, tkNotin, tkIs, tkIsnot, tkOf, tkAs, tkFrom: result = 5
|
|
||||||
of tkDotDot: result = 6
|
of tkDotDot: result = 6
|
||||||
|
of tkIn, tkNotin, tkIs, tkIsnot, tkOf, tkAs, tkFrom: result = 5
|
||||||
of tkAnd: result = 4
|
of tkAnd: result = 4
|
||||||
of tkOr, tkXor, tkPtr, tkRef: result = 3
|
of tkOr, tkXor, tkPtr, tkRef: result = 3
|
||||||
else: return -10
|
else: return -10
|
||||||
result = considerStrongSpaces(result)
|
|
||||||
|
|
||||||
|
proc newlineFollows*(L: Lexer): bool =
|
||||||
proc newlineFollows*(L: TLexer): bool =
|
|
||||||
var pos = L.bufpos
|
var pos = L.bufpos
|
||||||
while true:
|
while true:
|
||||||
case L.buf[pos]
|
case L.buf[pos]
|
||||||
|
|
@ -986,7 +968,7 @@ proc newlineFollows*(L: TLexer): bool =
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
proc skipMultiLineComment(L: var TLexer; tok: var TToken; start: int;
|
proc skipMultiLineComment(L: var Lexer; tok: var Token; start: int;
|
||||||
isDoc: bool) =
|
isDoc: bool) =
|
||||||
var pos = start
|
var pos = start
|
||||||
var toStrip = 0
|
var toStrip = 0
|
||||||
|
|
@ -1051,7 +1033,7 @@ proc skipMultiLineComment(L: var TLexer; tok: var TToken; start: int;
|
||||||
when defined(nimpretty):
|
when defined(nimpretty):
|
||||||
tok.commentOffsetB = L.offsetBase + pos - 1
|
tok.commentOffsetB = L.offsetBase + pos - 1
|
||||||
|
|
||||||
proc scanComment(L: var TLexer, tok: var TToken) =
|
proc scanComment(L: var Lexer, tok: var Token) =
|
||||||
var pos = L.bufpos
|
var pos = L.bufpos
|
||||||
tok.tokType = tkComment
|
tok.tokType = tkComment
|
||||||
# iNumber contains the number of '\n' in the token
|
# iNumber contains the number of '\n' in the token
|
||||||
|
|
@ -1101,7 +1083,7 @@ proc scanComment(L: var TLexer, tok: var TToken) =
|
||||||
when defined(nimpretty):
|
when defined(nimpretty):
|
||||||
tok.commentOffsetB = L.offsetBase + pos - 1
|
tok.commentOffsetB = L.offsetBase + pos - 1
|
||||||
|
|
||||||
proc skip(L: var TLexer, tok: var TToken) =
|
proc skip(L: var Lexer, tok: var Token) =
|
||||||
var pos = L.bufpos
|
var pos = L.bufpos
|
||||||
tokenBegin(tok, pos)
|
tokenBegin(tok, pos)
|
||||||
tok.strongSpaceA = 0
|
tok.strongSpaceA = 0
|
||||||
|
|
@ -1173,7 +1155,7 @@ proc skip(L: var TLexer, tok: var TToken) =
|
||||||
tok.tokType = tkComment
|
tok.tokType = tkComment
|
||||||
tok.indent = commentIndent
|
tok.indent = commentIndent
|
||||||
|
|
||||||
proc rawGetTok*(L: var TLexer, tok: var TToken) =
|
proc rawGetTok*(L: var Lexer, tok: var Token) =
|
||||||
template atTokenEnd() {.dirty.} =
|
template atTokenEnd() {.dirty.} =
|
||||||
when defined(nimsuggest):
|
when defined(nimsuggest):
|
||||||
# we attach the cursor to the last *strong* token
|
# we attach the cursor to the last *strong* token
|
||||||
|
|
@ -1181,8 +1163,6 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
|
||||||
L.previousToken.line = tok.line.uint16
|
L.previousToken.line = tok.line.uint16
|
||||||
L.previousToken.col = tok.col.int16
|
L.previousToken.col = tok.col.int16
|
||||||
|
|
||||||
when defined(nimsuggest):
|
|
||||||
L.cursor = CursorPosition.None
|
|
||||||
fillToken(tok)
|
fillToken(tok)
|
||||||
if L.indentAhead >= 0:
|
if L.indentAhead >= 0:
|
||||||
tok.indent = L.indentAhead
|
tok.indent = L.indentAhead
|
||||||
|
|
@ -1253,7 +1233,6 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
|
||||||
if L.fileIdx == L.config.m.trackPos.fileIndex and tok.col+1 == L.config.m.trackPos.col and
|
if L.fileIdx == L.config.m.trackPos.fileIndex and tok.col+1 == L.config.m.trackPos.col and
|
||||||
tok.line == L.config.m.trackPos.line.int and L.config.ideCmd == ideSug:
|
tok.line == L.config.m.trackPos.line.int and L.config.ideCmd == ideSug:
|
||||||
tok.tokType = tkDot
|
tok.tokType = tkDot
|
||||||
L.cursor = CursorPosition.InToken
|
|
||||||
L.config.m.trackPos.col = tok.col.int16
|
L.config.m.trackPos.col = tok.col.int16
|
||||||
inc(L.bufpos)
|
inc(L.bufpos)
|
||||||
atTokenEnd()
|
atTokenEnd()
|
||||||
|
|
@ -1326,8 +1305,8 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
|
||||||
|
|
||||||
proc getIndentWidth*(fileIdx: FileIndex, inputstream: PLLStream;
|
proc getIndentWidth*(fileIdx: FileIndex, inputstream: PLLStream;
|
||||||
cache: IdentCache; config: ConfigRef): int =
|
cache: IdentCache; config: ConfigRef): int =
|
||||||
var lex: TLexer
|
var lex: Lexer
|
||||||
var tok: TToken
|
var tok: Token
|
||||||
initToken(tok)
|
initToken(tok)
|
||||||
openLexer(lex, fileIdx, inputstream, cache, config)
|
openLexer(lex, fileIdx, inputstream, cache, config)
|
||||||
var prevToken = tkEof
|
var prevToken = tkEof
|
||||||
|
|
@ -1341,11 +1320,11 @@ proc getIndentWidth*(fileIdx: FileIndex, inputstream: PLLStream;
|
||||||
|
|
||||||
proc getPrecedence*(ident: PIdent): int =
|
proc getPrecedence*(ident: PIdent): int =
|
||||||
## assumes ident is binary operator already
|
## assumes ident is binary operator already
|
||||||
var tok: TToken
|
var tok: Token
|
||||||
initToken(tok)
|
initToken(tok)
|
||||||
tok.ident = ident
|
tok.ident = ident
|
||||||
tok.tokType =
|
tok.tokType =
|
||||||
if tok.ident.id in ord(tokKeywordLow) - ord(tkSymbol)..ord(tokKeywordHigh) - ord(tkSymbol):
|
if tok.ident.id in ord(tokKeywordLow) - ord(tkSymbol)..ord(tokKeywordHigh) - ord(tkSymbol):
|
||||||
TTokType(tok.ident.id + ord(tkSymbol))
|
TokType(tok.ident.id + ord(tkSymbol))
|
||||||
else: tkOpr
|
else: tkOpr
|
||||||
getPrecedence(tok, false)
|
getPrecedence(tok)
|
||||||
|
|
|
||||||
|
|
@ -919,11 +919,6 @@ template inst(field, t) =
|
||||||
proc isTrival(s: PSym): bool {.inline.} =
|
proc isTrival(s: PSym): bool {.inline.} =
|
||||||
s == nil or (s.ast != nil and s.ast[bodyPos].len == 0)
|
s == nil or (s.ast != nil and s.ast[bodyPos].len == 0)
|
||||||
|
|
||||||
|
|
||||||
proc isEmptyContainer(g: ModuleGraph, t: PType): bool =
|
|
||||||
(t.kind == tyArray and lengthOrd(g.config, t[0]) == 0) or
|
|
||||||
(t.kind == tySequence and t[0].kind == tyError)
|
|
||||||
|
|
||||||
proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo) =
|
proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo) =
|
||||||
## In the semantic pass this is called in strategic places
|
## In the semantic pass this is called in strategic places
|
||||||
## to ensure we lift assignment, destructors and moves properly.
|
## to ensure we lift assignment, destructors and moves properly.
|
||||||
|
|
|
||||||
|
|
@ -71,12 +71,9 @@ proc beautifyName(s: string, k: TSymKind): string =
|
||||||
|
|
||||||
proc differ*(line: string, a, b: int, x: string): string =
|
proc differ*(line: string, a, b: int, x: string): string =
|
||||||
proc substrEq(s: string, pos, last: int, substr: string): bool =
|
proc substrEq(s: string, pos, last: int, substr: string): bool =
|
||||||
var i = 0
|
result = true
|
||||||
while i < substr.len and pos+i <= last and s[pos+i] == substr[i]:
|
for i in 0..<substr.len:
|
||||||
inc i
|
if pos+i > last or s[pos+i] != substr[i]: return false
|
||||||
return i == substr.len
|
|
||||||
|
|
||||||
let last = min(b, line.len)
|
|
||||||
|
|
||||||
result = ""
|
result = ""
|
||||||
if not substrEq(line, a, b, x):
|
if not substrEq(line, a, b, x):
|
||||||
|
|
@ -84,11 +81,6 @@ proc differ*(line: string, a, b: int, x: string): string =
|
||||||
if cmpIgnoreStyle(y, x) == 0:
|
if cmpIgnoreStyle(y, x) == 0:
|
||||||
result = y
|
result = y
|
||||||
|
|
||||||
proc checkStyle(conf: ConfigRef; cache: IdentCache; info: TLineInfo, s: string, k: TSymKind; sym: PSym) =
|
|
||||||
let beau = beautifyName(s, k)
|
|
||||||
if s != beau:
|
|
||||||
lintReport(conf, info, beau, s)
|
|
||||||
|
|
||||||
proc nep1CheckDefImpl(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
|
proc nep1CheckDefImpl(conf: ConfigRef; info: TLineInfo; s: PSym; k: TSymKind) =
|
||||||
# operators stay as they are:
|
# operators stay as they are:
|
||||||
if k in {skResult, skTemp} or s.name.s[0] notin Letters: return
|
if k in {skResult, skTemp} or s.name.s[0] notin Letters: return
|
||||||
|
|
@ -136,6 +128,6 @@ proc styleCheckUse*(conf: ConfigRef; info: TLineInfo; s: PSym) =
|
||||||
lintReport(conf, info, newName, oldName)
|
lintReport(conf, info, newName, oldName)
|
||||||
|
|
||||||
proc checkPragmaUse*(conf: ConfigRef; info: TLineInfo; w: TSpecialWord; pragmaName: string) =
|
proc checkPragmaUse*(conf: ConfigRef; info: TLineInfo; w: TSpecialWord; pragmaName: string) =
|
||||||
let wanted = canonPragmaSpelling(w)
|
let wanted = specialWords[w]
|
||||||
if pragmaName != wanted:
|
if pragmaName != wanted:
|
||||||
lintReport(conf, info, wanted, pragmaName)
|
lintReport(conf, info, wanted, pragmaName)
|
||||||
|
|
|
||||||
|
|
@ -163,8 +163,8 @@ proc commandScan(cache: IdentCache, config: ConfigRef) =
|
||||||
var stream = llStreamOpen(f, fmRead)
|
var stream = llStreamOpen(f, fmRead)
|
||||||
if stream != nil:
|
if stream != nil:
|
||||||
var
|
var
|
||||||
L: TLexer
|
L: Lexer
|
||||||
tok: TToken
|
tok: Token
|
||||||
initToken(tok)
|
initToken(tok)
|
||||||
openLexer(L, f, stream, cache, config)
|
openLexer(L, f, stream, cache, config)
|
||||||
while true:
|
while true:
|
||||||
|
|
|
||||||
|
|
@ -91,8 +91,7 @@ when false:
|
||||||
if result.len > 0: return result
|
if result.len > 0: return result
|
||||||
|
|
||||||
proc scriptableImport(pkg, sub: string; info: TLineInfo): string =
|
proc scriptableImport(pkg, sub: string; info: TLineInfo): string =
|
||||||
result = resolveDollar(gProjectFull, info.toFullPath(), pkg, sub, info)
|
resolveDollar(gProjectFull, info.toFullPath(), pkg, sub, info)
|
||||||
if result.isNil: result = ""
|
|
||||||
|
|
||||||
proc lookupPackage(pkg, subdir: PNode): string =
|
proc lookupPackage(pkg, subdir: PNode): string =
|
||||||
let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: ""
|
let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: ""
|
||||||
|
|
@ -112,8 +111,7 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||||
try:
|
try:
|
||||||
result =
|
result = pathSubs(conf, n.strVal, toFullPath(conf, n.info).splitFile().dir)
|
||||||
pathSubs(conf, n.strVal, toFullPath(conf, n.info).splitFile().dir)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
localError(conf, n.info, "invalid path: " & n.strVal)
|
localError(conf, n.info, "invalid path: " & n.strVal)
|
||||||
result = n.strVal
|
result = n.strVal
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P
|
||||||
result = r
|
result = r
|
||||||
if result == nil:
|
if result == nil:
|
||||||
result = newModule(graph, fileIdx)
|
result = newModule(graph, fileIdx)
|
||||||
result.flags = result.flags + flags
|
result.flags.incl flags
|
||||||
result.id = id
|
result.id = id
|
||||||
registerModule(graph, result)
|
registerModule(graph, result)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -377,15 +377,12 @@ template styledMsgWriteln*(args: varargs[typed]) =
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
flushFile(stderr)
|
flushFile(stderr)
|
||||||
|
|
||||||
proc msgKindToString*(kind: TMsgKind): string =
|
proc msgKindToString*(kind: TMsgKind): string = MsgKindToStr[kind]
|
||||||
# later versions may provide translated error messages
|
# later versions may provide translated error messages
|
||||||
result = MsgKindToStr[kind]
|
|
||||||
|
|
||||||
proc getMessageStr(msg: TMsgKind, arg: string): string =
|
proc getMessageStr(msg: TMsgKind, arg: string): string = msgKindToString(msg) % [arg]
|
||||||
result = msgKindToString(msg) % [arg]
|
|
||||||
|
|
||||||
type
|
type TErrorHandling* = enum doNothing, doAbort, doRaise
|
||||||
TErrorHandling* = enum doNothing, doAbort, doRaise
|
|
||||||
|
|
||||||
proc log*(s: string) =
|
proc log*(s: string) =
|
||||||
var f: File
|
var f: File
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,13 @@ import
|
||||||
# ---------------- configuration file parser -----------------------------
|
# ---------------- configuration file parser -----------------------------
|
||||||
# we use Nim's scanner here to save space and work
|
# we use Nim's scanner here to save space and work
|
||||||
|
|
||||||
proc ppGetTok(L: var TLexer, tok: var TToken) =
|
proc ppGetTok(L: var Lexer, tok: var Token) =
|
||||||
# simple filter
|
# simple filter
|
||||||
rawGetTok(L, tok)
|
rawGetTok(L, tok)
|
||||||
while tok.tokType in {tkComment}: rawGetTok(L, tok)
|
while tok.tokType in {tkComment}: rawGetTok(L, tok)
|
||||||
|
|
||||||
proc parseExpr(L: var TLexer, tok: var TToken; config: ConfigRef): bool
|
proc parseExpr(L: var Lexer, tok: var Token; config: ConfigRef): bool
|
||||||
proc parseAtom(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
|
proc parseAtom(L: var Lexer, tok: var Token; config: ConfigRef): bool =
|
||||||
if tok.tokType == tkParLe:
|
if tok.tokType == tkParLe:
|
||||||
ppGetTok(L, tok)
|
ppGetTok(L, tok)
|
||||||
result = parseExpr(L, tok, config)
|
result = parseExpr(L, tok, config)
|
||||||
|
|
@ -35,21 +35,21 @@ proc parseAtom(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
|
||||||
result = isDefined(config, tok.ident.s)
|
result = isDefined(config, tok.ident.s)
|
||||||
ppGetTok(L, tok)
|
ppGetTok(L, tok)
|
||||||
|
|
||||||
proc parseAndExpr(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
|
proc parseAndExpr(L: var Lexer, tok: var Token; config: ConfigRef): bool =
|
||||||
result = parseAtom(L, tok, config)
|
result = parseAtom(L, tok, config)
|
||||||
while tok.tokType == tkAnd:
|
while tok.tokType == tkAnd:
|
||||||
ppGetTok(L, tok) # skip "and"
|
ppGetTok(L, tok) # skip "and"
|
||||||
var b = parseAtom(L, tok, config)
|
var b = parseAtom(L, tok, config)
|
||||||
result = result and b
|
result = result and b
|
||||||
|
|
||||||
proc parseExpr(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
|
proc parseExpr(L: var Lexer, tok: var Token; config: ConfigRef): bool =
|
||||||
result = parseAndExpr(L, tok, config)
|
result = parseAndExpr(L, tok, config)
|
||||||
while tok.tokType == tkOr:
|
while tok.tokType == tkOr:
|
||||||
ppGetTok(L, tok) # skip "or"
|
ppGetTok(L, tok) # skip "or"
|
||||||
var b = parseAndExpr(L, tok, config)
|
var b = parseAndExpr(L, tok, config)
|
||||||
result = result or b
|
result = result or b
|
||||||
|
|
||||||
proc evalppIf(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
|
proc evalppIf(L: var Lexer, tok: var Token; config: ConfigRef): bool =
|
||||||
ppGetTok(L, tok) # skip 'if' or 'elif'
|
ppGetTok(L, tok) # skip 'if' or 'elif'
|
||||||
result = parseExpr(L, tok, config)
|
result = parseExpr(L, tok, config)
|
||||||
if tok.tokType == tkColon: ppGetTok(L, tok)
|
if tok.tokType == tkColon: ppGetTok(L, tok)
|
||||||
|
|
@ -57,7 +57,7 @@ proc evalppIf(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
|
||||||
|
|
||||||
#var condStack: seq[bool] = @[]
|
#var condStack: seq[bool] = @[]
|
||||||
|
|
||||||
proc doEnd(L: var TLexer, tok: var TToken; condStack: var seq[bool]) =
|
proc doEnd(L: var Lexer, tok: var Token; condStack: var seq[bool]) =
|
||||||
if high(condStack) < 0: lexMessage(L, errGenerated, "expected @if")
|
if high(condStack) < 0: lexMessage(L, errGenerated, "expected @if")
|
||||||
ppGetTok(L, tok) # skip 'end'
|
ppGetTok(L, tok) # skip 'end'
|
||||||
setLen(condStack, high(condStack))
|
setLen(condStack, high(condStack))
|
||||||
|
|
@ -66,21 +66,21 @@ type
|
||||||
TJumpDest = enum
|
TJumpDest = enum
|
||||||
jdEndif, jdElseEndif
|
jdEndif, jdElseEndif
|
||||||
|
|
||||||
proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest; config: ConfigRef;
|
proc jumpToDirective(L: var Lexer, tok: var Token, dest: TJumpDest; config: ConfigRef;
|
||||||
condStack: var seq[bool])
|
condStack: var seq[bool])
|
||||||
proc doElse(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var seq[bool]) =
|
proc doElse(L: var Lexer, tok: var Token; config: ConfigRef; condStack: var seq[bool]) =
|
||||||
if high(condStack) < 0: lexMessage(L, errGenerated, "expected @if")
|
if high(condStack) < 0: lexMessage(L, errGenerated, "expected @if")
|
||||||
ppGetTok(L, tok)
|
ppGetTok(L, tok)
|
||||||
if tok.tokType == tkColon: ppGetTok(L, tok)
|
if tok.tokType == tkColon: ppGetTok(L, tok)
|
||||||
if condStack[high(condStack)]: jumpToDirective(L, tok, jdEndif, config, condStack)
|
if condStack[high(condStack)]: jumpToDirective(L, tok, jdEndif, config, condStack)
|
||||||
|
|
||||||
proc doElif(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var seq[bool]) =
|
proc doElif(L: var Lexer, tok: var Token; config: ConfigRef; condStack: var seq[bool]) =
|
||||||
if high(condStack) < 0: lexMessage(L, errGenerated, "expected @if")
|
if high(condStack) < 0: lexMessage(L, errGenerated, "expected @if")
|
||||||
var res = evalppIf(L, tok, config)
|
var res = evalppIf(L, tok, config)
|
||||||
if condStack[high(condStack)] or not res: jumpToDirective(L, tok, jdElseEndif, config, condStack)
|
if condStack[high(condStack)] or not res: jumpToDirective(L, tok, jdElseEndif, config, condStack)
|
||||||
else: condStack[high(condStack)] = true
|
else: condStack[high(condStack)] = true
|
||||||
|
|
||||||
proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest; config: ConfigRef;
|
proc jumpToDirective(L: var Lexer, tok: var Token, dest: TJumpDest; config: ConfigRef;
|
||||||
condStack: var seq[bool]) =
|
condStack: var seq[bool]) =
|
||||||
var nestedIfs = 0
|
var nestedIfs = 0
|
||||||
while true:
|
while true:
|
||||||
|
|
@ -110,7 +110,7 @@ proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest; config: Co
|
||||||
else:
|
else:
|
||||||
ppGetTok(L, tok)
|
ppGetTok(L, tok)
|
||||||
|
|
||||||
proc parseDirective(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var seq[bool]) =
|
proc parseDirective(L: var Lexer, tok: var Token; config: ConfigRef; condStack: var seq[bool]) =
|
||||||
ppGetTok(L, tok) # skip @
|
ppGetTok(L, tok) # skip @
|
||||||
case whichKeyword(tok.ident)
|
case whichKeyword(tok.ident)
|
||||||
of wIf:
|
of wIf:
|
||||||
|
|
@ -149,16 +149,16 @@ proc parseDirective(L: var TLexer, tok: var TToken; config: ConfigRef; condStack
|
||||||
else:
|
else:
|
||||||
lexMessage(L, errGenerated, "invalid directive: '$1'" % $tok)
|
lexMessage(L, errGenerated, "invalid directive: '$1'" % $tok)
|
||||||
|
|
||||||
proc confTok(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var seq[bool]) =
|
proc confTok(L: var Lexer, tok: var Token; config: ConfigRef; condStack: var seq[bool]) =
|
||||||
ppGetTok(L, tok)
|
ppGetTok(L, tok)
|
||||||
while tok.ident != nil and tok.ident.s == "@":
|
while tok.ident != nil and tok.ident.s == "@":
|
||||||
parseDirective(L, tok, config, condStack) # else: give the token to the parser
|
parseDirective(L, tok, config, condStack) # else: give the token to the parser
|
||||||
|
|
||||||
proc checkSymbol(L: TLexer, tok: TToken) =
|
proc checkSymbol(L: Lexer, tok: Token) =
|
||||||
if tok.tokType notin {tkSymbol..tkInt64Lit, tkStrLit..tkTripleStrLit}:
|
if tok.tokType notin {tkSymbol..tkInt64Lit, tkStrLit..tkTripleStrLit}:
|
||||||
lexMessage(L, errGenerated, "expected identifier, but got: " & $tok)
|
lexMessage(L, errGenerated, "expected identifier, but got: " & $tok)
|
||||||
|
|
||||||
proc parseAssignment(L: var TLexer, tok: var TToken;
|
proc parseAssignment(L: var Lexer, tok: var Token;
|
||||||
config: ConfigRef; condStack: var seq[bool]) =
|
config: ConfigRef; condStack: var seq[bool]) =
|
||||||
if tok.ident != nil:
|
if tok.ident != nil:
|
||||||
if tok.ident.s == "-" or tok.ident.s == "--":
|
if tok.ident.s == "-" or tok.ident.s == "--":
|
||||||
|
|
@ -211,8 +211,8 @@ proc parseAssignment(L: var TLexer, tok: var TToken;
|
||||||
proc readConfigFile*(filename: AbsoluteFile; cache: IdentCache;
|
proc readConfigFile*(filename: AbsoluteFile; cache: IdentCache;
|
||||||
config: ConfigRef): bool =
|
config: ConfigRef): bool =
|
||||||
var
|
var
|
||||||
L: TLexer
|
L: Lexer
|
||||||
tok: TToken
|
tok: Token
|
||||||
stream: PLLStream
|
stream: PLLStream
|
||||||
stream = llStreamOpen(filename, fmRead)
|
stream = llStreamOpen(filename, fmRead)
|
||||||
if stream != nil:
|
if stream != nil:
|
||||||
|
|
|
||||||
|
|
@ -162,9 +162,9 @@ proc getColNumber(L: TBaseLexer, pos: int): int =
|
||||||
proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
|
proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
|
||||||
result = ""
|
result = ""
|
||||||
var i = L.lineStart
|
var i = L.lineStart
|
||||||
while not (L.buf[i] in {CR, LF, EndOfFile}):
|
while L.buf[i] notin {CR, LF, EndOfFile}:
|
||||||
result.add(L.buf[i])
|
result.add L.buf[i]
|
||||||
inc(i)
|
inc i
|
||||||
result.add("\n")
|
result.add "\n"
|
||||||
if marker:
|
if marker:
|
||||||
result.add(spaces(getColNumber(L, L.bufpos)) & '^' & "\n")
|
result.add spaces(getColNumber(L, L.bufpos)) & '^' & "\n"
|
||||||
|
|
|
||||||
|
|
@ -691,12 +691,10 @@ iterator nimbleSubs*(conf: ConfigRef; p: string): string =
|
||||||
proc toGeneratedFile*(conf: ConfigRef; path: AbsoluteFile,
|
proc toGeneratedFile*(conf: ConfigRef; path: AbsoluteFile,
|
||||||
ext: string): AbsoluteFile =
|
ext: string): AbsoluteFile =
|
||||||
## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
|
## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
|
||||||
let (head, tail) = splitPath(path.string)
|
result = getNimcacheDir(conf) / RelativeFile path.string.splitPath.tail.changeFileExt(ext)
|
||||||
result = getNimcacheDir(conf) / RelativeFile changeFileExt(tail, ext)
|
|
||||||
|
|
||||||
proc completeGeneratedFilePath*(conf: ConfigRef; f: AbsoluteFile,
|
proc completeGeneratedFilePath*(conf: ConfigRef; f: AbsoluteFile,
|
||||||
createSubDir: bool = true): AbsoluteFile =
|
createSubDir: bool = true): AbsoluteFile =
|
||||||
let (head, tail) = splitPath(f.string)
|
|
||||||
let subdir = getNimcacheDir(conf)
|
let subdir = getNimcacheDir(conf)
|
||||||
if createSubDir:
|
if createSubDir:
|
||||||
try:
|
try:
|
||||||
|
|
@ -704,7 +702,7 @@ proc completeGeneratedFilePath*(conf: ConfigRef; f: AbsoluteFile,
|
||||||
except OSError:
|
except OSError:
|
||||||
writeLine(stdout, "cannot create directory: " & subdir.string)
|
writeLine(stdout, "cannot create directory: " & subdir.string)
|
||||||
quit(1)
|
quit(1)
|
||||||
result = subdir / RelativeFile tail
|
result = subdir / RelativeFile f.string.splitPath.tail
|
||||||
#echo "completeGeneratedFilePath(", f, ") = ", result
|
#echo "completeGeneratedFilePath(", f, ") = ", result
|
||||||
|
|
||||||
proc rawFindFile(conf: ConfigRef; f: RelativeFile; suppressStdlib: bool): AbsoluteFile =
|
proc rawFindFile(conf: ConfigRef; f: RelativeFile; suppressStdlib: bool): AbsoluteFile =
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,6 @@ proc getNimbleFile*(conf: ConfigRef; path: string): string =
|
||||||
result = file
|
result = file
|
||||||
break packageSearch
|
break packageSearch
|
||||||
# we also store if we didn't find anything:
|
# we also store if we didn't find anything:
|
||||||
when not defined(nimNoNilSeqs):
|
|
||||||
if result.isNil: result = ""
|
|
||||||
for d in myParentDirs(path):
|
for d in myParentDirs(path):
|
||||||
#echo "set cache ", d, " |", result, "|", parents
|
#echo "set cache ", d, " |", result, "|", parents
|
||||||
conf.packageCache[d] = result
|
conf.packageCache[d] = result
|
||||||
|
|
|
||||||
|
|
@ -99,14 +99,14 @@ proc compileConstraints(p: PNode, result: var TPatternCode; conf: ConfigRef) =
|
||||||
else:
|
else:
|
||||||
# check all symkinds:
|
# check all symkinds:
|
||||||
internalAssert conf, int(high(TSymKind)) < 255
|
internalAssert conf, int(high(TSymKind)) < 255
|
||||||
for i in low(TSymKind)..high(TSymKind):
|
for i in TSymKind:
|
||||||
if cmpIgnoreStyle(($i).substr(2), spec) == 0:
|
if cmpIgnoreStyle(($i).substr(2), spec) == 0:
|
||||||
result.add(ppSymKind)
|
result.add(ppSymKind)
|
||||||
result.add(chr(i.ord))
|
result.add(chr(i.ord))
|
||||||
return
|
return
|
||||||
# check all nodekinds:
|
# check all nodekinds:
|
||||||
internalAssert conf, int(high(TNodeKind)) < 255
|
internalAssert conf, int(high(TNodeKind)) < 255
|
||||||
for i in low(TNodeKind)..high(TNodeKind):
|
for i in TNodeKind:
|
||||||
if cmpIgnoreStyle($i, spec) == 0:
|
if cmpIgnoreStyle($i, spec) == 0:
|
||||||
result.add(ppNodeKind)
|
result.add(ppNodeKind)
|
||||||
result.add(chr(i.ord))
|
result.add(chr(i.ord))
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -126,7 +126,7 @@ proc moduleHasChanged*(graph: ModuleGraph; module: PSym): bool {.inline.} =
|
||||||
proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {.discardable.} =
|
proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {.discardable.} =
|
||||||
if graph.stopCompile(): return true
|
if graph.stopCompile(): return true
|
||||||
var
|
var
|
||||||
p: TParsers
|
p: Parser
|
||||||
a: TPassContextArray
|
a: TPassContextArray
|
||||||
s: PLLStream
|
s: PLLStream
|
||||||
fileIdx = module.fileIdx
|
fileIdx = module.fileIdx
|
||||||
|
|
@ -164,7 +164,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
|
||||||
else:
|
else:
|
||||||
s = stream
|
s = stream
|
||||||
while true:
|
while true:
|
||||||
openParsers(p, fileIdx, s, graph.cache, graph.config)
|
openParser(p, fileIdx, s, graph.cache, graph.config)
|
||||||
|
|
||||||
if module.owner == nil or module.owner.name.s != "stdlib" or module.name.s == "distros":
|
if module.owner == nil or module.owner.name.s != "stdlib" or module.name.s == "distros":
|
||||||
# XXX what about caching? no processing then? what if I change the
|
# XXX what about caching? no processing then? what if I change the
|
||||||
|
|
@ -212,7 +212,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
|
||||||
else:
|
else:
|
||||||
#echo "----- single\n", n
|
#echo "----- single\n", n
|
||||||
if not processTopLevelStmt(graph, n, a): break
|
if not processTopLevelStmt(graph, n, a): break
|
||||||
closeParsers(p)
|
closeParser(p)
|
||||||
if s.kind != llsStdIn: break
|
if s.kind != llsStdIn: break
|
||||||
closePasses(graph, a)
|
closePasses(graph, a)
|
||||||
# id synchronization point for more consistent code generation:
|
# id synchronization point for more consistent code generation:
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,7 @@ proc processMagic(c: PContext, n: PNode, s: PSym) =
|
||||||
var v: string
|
var v: string
|
||||||
if n[1].kind == nkIdent: v = n[1].ident.s
|
if n[1].kind == nkIdent: v = n[1].ident.s
|
||||||
else: v = expectStrLit(c, n)
|
else: v = expectStrLit(c, n)
|
||||||
for m in low(TMagic)..high(TMagic):
|
for m in TMagic:
|
||||||
if substr($m, 1) == v:
|
if substr($m, 1) == v:
|
||||||
s.magic = m
|
s.magic = m
|
||||||
break
|
break
|
||||||
|
|
@ -257,8 +257,8 @@ proc isTurnedOn(c: PContext, n: PNode): bool =
|
||||||
localError(c.config, n.info, "'on' or 'off' expected")
|
localError(c.config, n.info, "'on' or 'off' expected")
|
||||||
|
|
||||||
proc onOff(c: PContext, n: PNode, op: TOptions, resOptions: var TOptions) =
|
proc onOff(c: PContext, n: PNode, op: TOptions, resOptions: var TOptions) =
|
||||||
if isTurnedOn(c, n): resOptions = resOptions + op
|
if isTurnedOn(c, n): resOptions.incl op
|
||||||
else: resOptions = resOptions - op
|
else: resOptions.excl op
|
||||||
|
|
||||||
proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) =
|
proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) =
|
||||||
if isTurnedOn(c, n):
|
if isTurnedOn(c, n):
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ type
|
||||||
renderIr
|
renderIr
|
||||||
TRenderFlags* = set[TRenderFlag]
|
TRenderFlags* = set[TRenderFlag]
|
||||||
TRenderTok* = object
|
TRenderTok* = object
|
||||||
kind*: TTokType
|
kind*: TokType
|
||||||
length*: int16
|
length*: int16
|
||||||
sym*: PSym
|
sym*: PSym
|
||||||
|
|
||||||
|
|
@ -118,7 +118,7 @@ proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags; config: ConfigRef) =
|
||||||
g.inGenericParams = false
|
g.inGenericParams = false
|
||||||
g.config = config
|
g.config = config
|
||||||
|
|
||||||
proc addTok(g: var TSrcGen, kind: TTokType, s: string; sym: PSym = nil) =
|
proc addTok(g: var TSrcGen, kind: TokType, s: string; sym: PSym = nil) =
|
||||||
setLen(g.tokens, g.tokens.len + 1)
|
setLen(g.tokens, g.tokens.len + 1)
|
||||||
g.tokens[^1].kind = kind
|
g.tokens[^1].kind = kind
|
||||||
g.tokens[^1].length = int16(s.len)
|
g.tokens[^1].length = int16(s.len)
|
||||||
|
|
@ -178,7 +178,7 @@ proc dedent(g: var TSrcGen) =
|
||||||
dec(g.pendingNL, IndentWidth)
|
dec(g.pendingNL, IndentWidth)
|
||||||
dec(g.lineLen, IndentWidth)
|
dec(g.lineLen, IndentWidth)
|
||||||
|
|
||||||
proc put(g: var TSrcGen, kind: TTokType, s: string; sym: PSym = nil) =
|
proc put(g: var TSrcGen, kind: TokType, s: string; sym: PSym = nil) =
|
||||||
if kind != tkSpaces:
|
if kind != tkSpaces:
|
||||||
addPendingNL(g)
|
addPendingNL(g)
|
||||||
if s.len > 0:
|
if s.len > 0:
|
||||||
|
|
@ -250,7 +250,7 @@ proc maxLineLength(s: string): int =
|
||||||
inc(lineLen)
|
inc(lineLen)
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
proc putRawStr(g: var TSrcGen, kind: TTokType, s: string) =
|
proc putRawStr(g: var TSrcGen, kind: TokType, s: string) =
|
||||||
var i = 0
|
var i = 0
|
||||||
let hi = s.len - 1
|
let hi = s.len - 1
|
||||||
var str = ""
|
var str = ""
|
||||||
|
|
@ -459,8 +459,8 @@ proc lsub(g: TSrcGen; n: PNode): int =
|
||||||
of nkDo: result = lsons(g, n) + len("do__:_")
|
of nkDo: result = lsons(g, n) + len("do__:_")
|
||||||
of nkConstDef, nkIdentDefs:
|
of nkConstDef, nkIdentDefs:
|
||||||
result = lcomma(g, n, 0, - 3)
|
result = lcomma(g, n, 0, - 3)
|
||||||
if n[^2].kind != nkEmpty: result = result + lsub(g, n[^2]) + 2
|
if n[^2].kind != nkEmpty: result += lsub(g, n[^2]) + 2
|
||||||
if n[^1].kind != nkEmpty: result = result + lsub(g, n[^1]) + 3
|
if n[^1].kind != nkEmpty: result += lsub(g, n[^1]) + 3
|
||||||
of nkVarTuple:
|
of nkVarTuple:
|
||||||
if n[^1].kind == nkEmpty:
|
if n[^1].kind == nkEmpty:
|
||||||
result = lcomma(g, n, 0, - 2) + len("()")
|
result = lcomma(g, n, 0, - 2) + len("()")
|
||||||
|
|
@ -471,8 +471,8 @@ proc lsub(g: TSrcGen; n: PNode): int =
|
||||||
of nkChckRange: result = len("chckRange") + 2 + lcomma(g, n)
|
of nkChckRange: result = len("chckRange") + 2 + lcomma(g, n)
|
||||||
of nkObjDownConv, nkObjUpConv:
|
of nkObjDownConv, nkObjUpConv:
|
||||||
result = 2
|
result = 2
|
||||||
if n.len >= 1: result = result + lsub(g, n[0])
|
if n.len >= 1: result += lsub(g, n[0])
|
||||||
result = result + lcomma(g, n, 1)
|
result += lcomma(g, n, 1)
|
||||||
of nkExprColonExpr: result = lsons(g, n) + 2
|
of nkExprColonExpr: result = lsons(g, n) + 2
|
||||||
of nkInfix: result = lsons(g, n) + 2
|
of nkInfix: result = lsons(g, n) + 2
|
||||||
of nkPrefix:
|
of nkPrefix:
|
||||||
|
|
@ -536,7 +536,7 @@ proc lsub(g: TSrcGen; n: PNode): int =
|
||||||
of nkGenericParams: result = lcomma(g, n) + 2
|
of nkGenericParams: result = lcomma(g, n) + 2
|
||||||
of nkFormalParams:
|
of nkFormalParams:
|
||||||
result = lcomma(g, n, 1) + 2
|
result = lcomma(g, n, 1) + 2
|
||||||
if n[0].kind != nkEmpty: result = result + lsub(g, n[0]) + 2
|
if n[0].kind != nkEmpty: result += lsub(g, n[0]) + 2
|
||||||
of nkExceptBranch:
|
of nkExceptBranch:
|
||||||
result = lcomma(g, n, 0, -2) + lsub(g, lastSon(n)) + len("except_:_")
|
result = lcomma(g, n, 0, -2) + lsub(g, lastSon(n)) + len("except_:_")
|
||||||
of nkObjectTy:
|
of nkObjectTy:
|
||||||
|
|
@ -575,7 +575,7 @@ proc hasCom(n: PNode): bool =
|
||||||
for i in 0..<n.len:
|
for i in 0..<n.len:
|
||||||
if hasCom(n[i]): return true
|
if hasCom(n[i]): return true
|
||||||
|
|
||||||
proc putWithSpace(g: var TSrcGen, kind: TTokType, s: string) =
|
proc putWithSpace(g: var TSrcGen, kind: TokType, s: string) =
|
||||||
put(g, kind, s)
|
put(g, kind, s)
|
||||||
put(g, tkSpaces, Space)
|
put(g, tkSpaces, Space)
|
||||||
|
|
||||||
|
|
@ -618,7 +618,7 @@ proc gsons(g: var TSrcGen, n: PNode, c: TContext, start: int = 0,
|
||||||
theEnd: int = - 1) =
|
theEnd: int = - 1) =
|
||||||
for i in start..n.len + theEnd: gsub(g, n[i], c)
|
for i in start..n.len + theEnd: gsub(g, n[i], c)
|
||||||
|
|
||||||
proc gsection(g: var TSrcGen, n: PNode, c: TContext, kind: TTokType,
|
proc gsection(g: var TSrcGen, n: PNode, c: TContext, kind: TokType,
|
||||||
k: string) =
|
k: string) =
|
||||||
if n.len == 0: return # empty var sections are possible
|
if n.len == 0: return # empty var sections are possible
|
||||||
putWithSpace(g, kind, k)
|
putWithSpace(g, kind, k)
|
||||||
|
|
@ -847,7 +847,7 @@ proc gident(g: var TSrcGen, n: PNode) =
|
||||||
if sfAnon in n.sym.flags or
|
if sfAnon in n.sym.flags or
|
||||||
(n.typ != nil and tfImplicitTypeParam in n.typ.flags): return
|
(n.typ != nil and tfImplicitTypeParam in n.typ.flags): return
|
||||||
|
|
||||||
var t: TTokType
|
var t: TokType
|
||||||
var s = atom(g, n)
|
var s = atom(g, n)
|
||||||
if s.len > 0 and s[0] in lexer.SymChars:
|
if s.len > 0 and s[0] in lexer.SymChars:
|
||||||
if n.kind == nkIdent:
|
if n.kind == nkIdent:
|
||||||
|
|
@ -855,7 +855,7 @@ proc gident(g: var TSrcGen, n: PNode) =
|
||||||
(n.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)):
|
(n.ident.id > ord(tokKeywordHigh) - ord(tkSymbol)):
|
||||||
t = tkSymbol
|
t = tkSymbol
|
||||||
else:
|
else:
|
||||||
t = TTokType(n.ident.id + ord(tkSymbol))
|
t = TokType(n.ident.id + ord(tkSymbol))
|
||||||
else:
|
else:
|
||||||
t = tkSymbol
|
t = tkSymbol
|
||||||
else:
|
else:
|
||||||
|
|
@ -1644,7 +1644,7 @@ proc initTokRender*(r: var TSrcGen, n: PNode, renderFlags: TRenderFlags = {}) =
|
||||||
initSrcGen(r, renderFlags, newPartialConfigRef())
|
initSrcGen(r, renderFlags, newPartialConfigRef())
|
||||||
gsub(r, n)
|
gsub(r, n)
|
||||||
|
|
||||||
proc getNextTok*(r: var TSrcGen, kind: var TTokType, literal: var string) =
|
proc getNextTok*(r: var TSrcGen, kind: var TokType, literal: var string) =
|
||||||
if r.idx < r.tokens.len:
|
if r.idx < r.tokens.len:
|
||||||
kind = r.tokens[r.idx].kind
|
kind = r.tokens[r.idx].kind
|
||||||
let length = r.tokens[r.idx].length.int
|
let length = r.tokens[r.idx].length.int
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,6 @@ proc extractRunnableExamplesSource*(conf: ConfigRef; n: PNode): string =
|
||||||
var indent = info.col
|
var indent = info.col
|
||||||
let numLines = numLines(conf, info.fileIndex).uint16
|
let numLines = numLines(conf, info.fileIndex).uint16
|
||||||
var lastNonemptyPos = 0
|
var lastNonemptyPos = 0
|
||||||
result = ""
|
|
||||||
|
|
||||||
var ldata = LineData(lineFirst: first.line.int, conf: conf)
|
var ldata = LineData(lineFirst: first.line.int, conf: conf)
|
||||||
visitMultilineStrings(ldata, n[^1])
|
visitMultilineStrings(ldata, n[^1])
|
||||||
|
|
@ -116,6 +115,7 @@ proc extractRunnableExamplesSource*(conf: ConfigRef; n: PNode): string =
|
||||||
for i in 0..<ldata.lines.len:
|
for i in 0..<ldata.lines.len:
|
||||||
echo (i+ldata.lineFirst, ldata.lines[i])
|
echo (i+ldata.lineFirst, ldata.lines[i])
|
||||||
|
|
||||||
|
result = ""
|
||||||
for line in first.line..numLines: # bugfix, see `testNimDocTrailingExample`
|
for line in first.line..numLines: # bugfix, see `testNimDocTrailingExample`
|
||||||
info.line = line
|
info.line = line
|
||||||
let src = sourceLine(conf, info)
|
let src = sourceLine(conf, info)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
intsets, ast, idents, algorithm, renderer, os, strutils,
|
intsets, ast, idents, algorithm, renderer, strutils,
|
||||||
msgs, modulegraphs, syntaxes, options, modulepaths,
|
msgs, modulegraphs, syntaxes, options, modulepaths,
|
||||||
lineinfos
|
lineinfos
|
||||||
|
|
||||||
|
|
@ -108,28 +108,6 @@ proc computeDeps(cache: IdentCache; n: PNode, declares, uses: var IntSet; topLev
|
||||||
else:
|
else:
|
||||||
for i in 0..<n.safeLen: deps(n[i])
|
for i in 0..<n.safeLen: deps(n[i])
|
||||||
|
|
||||||
proc cleanPath(s: string): string =
|
|
||||||
# Here paths may have the form A / B or "A/B"
|
|
||||||
result = ""
|
|
||||||
for c in s:
|
|
||||||
if c != ' ' and c != '\"':
|
|
||||||
result.add c
|
|
||||||
|
|
||||||
proc joinPath(parts: seq[string]): string =
|
|
||||||
let nb = parts.len
|
|
||||||
assert nb > 0
|
|
||||||
if nb == 1:
|
|
||||||
return parts[0]
|
|
||||||
result = parts[0] / parts[1]
|
|
||||||
for i in 2..<parts.len:
|
|
||||||
result = result / parts[i]
|
|
||||||
|
|
||||||
proc getIncludePath(n: PNode, modulePath: string): string =
|
|
||||||
let istr = n.renderTree.cleanPath
|
|
||||||
let (pdir, _) = modulePath.splitPath
|
|
||||||
let p = istr.split('/').joinPath.addFileExt("nim")
|
|
||||||
result = pdir / p
|
|
||||||
|
|
||||||
proc hasIncludes(n:PNode): bool =
|
proc hasIncludes(n:PNode): bool =
|
||||||
for a in n:
|
for a in n:
|
||||||
if a.kind == nkIncludeStmt:
|
if a.kind == nkIncludeStmt:
|
||||||
|
|
@ -409,8 +387,7 @@ proc strongConnect(v: var DepN, idx: var int, s: var seq[DepN],
|
||||||
proc getStrongComponents(g: var DepG): seq[seq[DepN]] =
|
proc getStrongComponents(g: var DepG): seq[seq[DepN]] =
|
||||||
## Tarjan's algorithm. Performs a topological sort
|
## Tarjan's algorithm. Performs a topological sort
|
||||||
## and detects strongly connected components.
|
## and detects strongly connected components.
|
||||||
result = newSeq[seq[DepN]]()
|
var s: seq[DepN]
|
||||||
var s = newSeq[DepN]()
|
|
||||||
var idx = 0
|
var idx = 0
|
||||||
for v in g.mitems:
|
for v in g.mitems:
|
||||||
if v.idx < 0:
|
if v.idx < 0:
|
||||||
|
|
|
||||||
|
|
@ -80,16 +80,14 @@ proc decodeStr*(s: cstring, pos: var int): string =
|
||||||
else: break
|
else: break
|
||||||
pos = i
|
pos = i
|
||||||
|
|
||||||
const
|
const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
|
|
||||||
{.push overflowChecks: off.}
|
{.push overflowChecks: off.}
|
||||||
|
|
||||||
# since negative numbers require a leading '-' they use up 1 byte. Thus we
|
# since negative numbers require a leading '-' they use up 1 byte. Thus we
|
||||||
# subtract/add `vintDelta` here to save space for small negative numbers
|
# subtract/add `vintDelta` here to save space for small negative numbers
|
||||||
# which are common in ROD files:
|
# which are common in ROD files:
|
||||||
const
|
const vintDelta = 5
|
||||||
vintDelta = 5
|
|
||||||
|
|
||||||
template encodeIntImpl(self) =
|
template encodeIntImpl(self) =
|
||||||
var d: char
|
var d: char
|
||||||
|
|
|
||||||
|
|
@ -2154,7 +2154,7 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType;
|
||||||
# since it's an instantiation, we unmark it as a compilerproc. Otherwise
|
# since it's an instantiation, we unmark it as a compilerproc. Otherwise
|
||||||
# codegen would fail:
|
# codegen would fail:
|
||||||
if sfCompilerProc in result.flags:
|
if sfCompilerProc in result.flags:
|
||||||
result.flags = result.flags - {sfCompilerProc, sfExportc, sfImportc}
|
result.flags.excl {sfCompilerProc, sfExportc, sfImportc}
|
||||||
result.loc.r = nil
|
result.loc.r = nil
|
||||||
|
|
||||||
proc setMs(n: PNode, s: PSym): PNode =
|
proc setMs(n: PNode, s: PSym): PNode =
|
||||||
|
|
|
||||||
|
|
@ -475,7 +475,7 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
else:
|
else:
|
||||||
localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
|
localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
|
||||||
of nkBracket:
|
of nkBracket:
|
||||||
idx = idx - toInt64(firstOrd(g.config, x.typ))
|
idx -= toInt64(firstOrd(g.config, x.typ))
|
||||||
if idx >= 0 and idx < x.len: result = x[int(idx)]
|
if idx >= 0 and idx < x.len: result = x[int(idx)]
|
||||||
else: localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
|
else: localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
|
||||||
of nkStrLit..nkTripleStrLit:
|
of nkStrLit..nkTripleStrLit:
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym
|
||||||
continue
|
continue
|
||||||
let symKind = if q.typ.kind == tyStatic: skConst else: skType
|
let symKind = if q.typ.kind == tyStatic: skConst else: skType
|
||||||
var s = newSym(symKind, q.name, getCurrOwner(c), q.info)
|
var s = newSym(symKind, q.name, getCurrOwner(c), q.info)
|
||||||
s.flags = s.flags + {sfUsed, sfFromGeneric}
|
s.flags.incl {sfUsed, sfFromGeneric}
|
||||||
var t = PType(idTableGet(pt, q.typ))
|
var t = PType(idTableGet(pt, q.typ))
|
||||||
if t == nil:
|
if t == nil:
|
||||||
if tfRetType in q.typ.flags:
|
if tfRetType in q.typ.flags:
|
||||||
|
|
|
||||||
|
|
@ -139,8 +139,7 @@ template quoteStr(s: string): string = "'" & s & "'"
|
||||||
proc fieldsPresentInInitExpr(c: PContext, fieldsRecList, initExpr: PNode): string =
|
proc fieldsPresentInInitExpr(c: PContext, fieldsRecList, initExpr: PNode): string =
|
||||||
result = ""
|
result = ""
|
||||||
for field in directFieldsInRecList(fieldsRecList):
|
for field in directFieldsInRecList(fieldsRecList):
|
||||||
let assignment = locateFieldInInitExpr(c, field.sym, initExpr)
|
if locateFieldInInitExpr(c, field.sym, initExpr) != nil:
|
||||||
if assignment != nil:
|
|
||||||
if result.len != 0: result.add ", "
|
if result.len != 0: result.add ", "
|
||||||
result.add field.sym.name.s.quoteStr
|
result.add field.sym.name.s.quoteStr
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,6 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
let s = qualifiedLookUp(c.c, n, {})
|
let s = qualifiedLookUp(c.c, n, {})
|
||||||
if s != nil:
|
if s != nil:
|
||||||
if s.owner == c.owner and s.kind == skParam and sfTemplateParam in s.flags:
|
if s.owner == c.owner and s.kind == skParam and sfTemplateParam in s.flags:
|
||||||
# oldCheck(c, sfGenSym notin s.flags or c.noGenSym == 0):
|
|
||||||
incl(s.flags, sfUsed)
|
incl(s.flags, sfUsed)
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
onUse(n.info, s)
|
onUse(n.info, s)
|
||||||
|
|
|
||||||
|
|
@ -786,7 +786,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||||
{sfImportc, sfExportc} * fieldOwner.flags != {} and
|
{sfImportc, sfExportc} * fieldOwner.flags != {} and
|
||||||
not hasCaseFields and f.loc.r == nil:
|
not hasCaseFields and f.loc.r == nil:
|
||||||
f.loc.r = rope(f.name.s)
|
f.loc.r = rope(f.name.s)
|
||||||
f.flags = f.flags + ({sfImportc, sfExportc} * fieldOwner.flags)
|
f.flags.incl {sfImportc, sfExportc} * fieldOwner.flags
|
||||||
inc(pos)
|
inc(pos)
|
||||||
if containsOrIncl(check, f.name.id):
|
if containsOrIncl(check, f.name.id):
|
||||||
localError(c.config, info, "attempt to redefine: '" & f.name.s & "'")
|
localError(c.config, info, "attempt to redefine: '" & f.name.s & "'")
|
||||||
|
|
@ -1211,11 +1211,9 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
|
|
||||||
if hasType:
|
if hasType:
|
||||||
typ = semParamType(c, a[^2], constraint)
|
typ = semParamType(c, a[^2], constraint)
|
||||||
let sym = getCurrOwner(c)
|
|
||||||
var owner = sym.owner
|
|
||||||
# TODO: Disallow typed/untyped in procs in the compiler/stdlib
|
# TODO: Disallow typed/untyped in procs in the compiler/stdlib
|
||||||
if kind == skProc and (typ.kind == tyTyped or typ.kind == tyUntyped):
|
if kind == skProc and (typ.kind == tyTyped or typ.kind == tyUntyped):
|
||||||
if not isMagic(sym):
|
if not isMagic(getCurrOwner(c)):
|
||||||
localError(c.config, a[^2].info, "'" & typ.sym.name.s & "' is only allowed in templates and macros or magic procs")
|
localError(c.config, a[^2].info, "'" & typ.sym.name.s & "' is only allowed in templates and macros or magic procs")
|
||||||
|
|
||||||
if hasDefault:
|
if hasDefault:
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,7 @@
|
||||||
import ast, astalgo, msgs, types, magicsys, semdata, renderer, options,
|
import ast, astalgo, msgs, types, magicsys, semdata, renderer, options,
|
||||||
lineinfos
|
lineinfos
|
||||||
|
|
||||||
const
|
const tfInstClearedFlags = {tfHasMeta, tfUnresolved}
|
||||||
tfInstClearedFlags = {tfHasMeta, tfUnresolved}
|
|
||||||
|
|
||||||
proc checkPartialConstructedType(conf: ConfigRef; info: TLineInfo, t: PType) =
|
proc checkPartialConstructedType(conf: ConfigRef; info: TLineInfo, t: PType) =
|
||||||
if t.kind in {tyVar, tyLent} and t[0].kind in {tyVar, tyLent}:
|
if t.kind in {tyVar, tyLent} and t[0].kind in {tyVar, tyLent}:
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
|
||||||
if t.n.len > 0:
|
if t.n.len > 0:
|
||||||
let oldFlags = t.sym.flags
|
let oldFlags = t.sym.flags
|
||||||
# Mild hack to prevent endless recursion.
|
# Mild hack to prevent endless recursion.
|
||||||
t.sym.flags = t.sym.flags - {sfAnon, sfGenSym}
|
t.sym.flags.excl {sfAnon, sfGenSym}
|
||||||
hashTree(c, t.n, flags + {CoHashTypeInsideNode})
|
hashTree(c, t.n, flags + {CoHashTypeInsideNode})
|
||||||
t.sym.flags = oldFlags
|
t.sym.flags = oldFlags
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -265,17 +265,12 @@ proc sumGeneric(t: PType): int =
|
||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
#var ggDebug: bool
|
|
||||||
|
|
||||||
proc complexDisambiguation(a, b: PType): int =
|
proc complexDisambiguation(a, b: PType): int =
|
||||||
# 'a' matches better if *every* argument matches better or equal than 'b'.
|
# 'a' matches better if *every* argument matches better or equal than 'b'.
|
||||||
var winner = 0
|
var winner = 0
|
||||||
for i in 1..<min(a.len, b.len):
|
for i in 1..<min(a.len, b.len):
|
||||||
let x = a[i].sumGeneric
|
let x = a[i].sumGeneric
|
||||||
let y = b[i].sumGeneric
|
let y = b[i].sumGeneric
|
||||||
#if ggDebug:
|
|
||||||
#echo "came herA ", typeToString(a[i]), " ", x
|
|
||||||
#echo "came herB ", typeToString(b[i]), " ", y
|
|
||||||
if x != y:
|
if x != y:
|
||||||
if winner == 0:
|
if winner == 0:
|
||||||
if x > y: winner = 1
|
if x > y: winner = 1
|
||||||
|
|
@ -337,14 +332,13 @@ proc argTypeToString(arg: PNode; prefer: TPreferedDesc): string =
|
||||||
else:
|
else:
|
||||||
result = arg.typ.typeToString(prefer)
|
result = arg.typ.typeToString(prefer)
|
||||||
|
|
||||||
proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
|
proc describeArgs*(c: PContext, n: PNode, startIdx = 1; prefer = preferName): string =
|
||||||
prefer: TPreferedDesc = preferName): string =
|
|
||||||
result = ""
|
result = ""
|
||||||
for i in startIdx..<n.len:
|
for i in startIdx..<n.len:
|
||||||
var arg = n[i]
|
var arg = n[i]
|
||||||
if n[i].kind == nkExprEqExpr:
|
if n[i].kind == nkExprEqExpr:
|
||||||
result.add(renderTree(n[i][0]))
|
result.add renderTree(n[i][0])
|
||||||
result.add(": ")
|
result.add ": "
|
||||||
if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo}:
|
if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo}:
|
||||||
# XXX we really need to 'tryExpr' here!
|
# XXX we really need to 'tryExpr' here!
|
||||||
arg = c.semOperand(c, n[i][1])
|
arg = c.semOperand(c, n[i][1])
|
||||||
|
|
@ -357,8 +351,8 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
|
||||||
arg = c.semOperand(c, n[i])
|
arg = c.semOperand(c, n[i])
|
||||||
n[i] = arg
|
n[i] = arg
|
||||||
if arg.typ != nil and arg.typ.kind == tyError: return
|
if arg.typ != nil and arg.typ.kind == tyError: return
|
||||||
result.add(argTypeToString(arg, prefer))
|
result.add argTypeToString(arg, prefer)
|
||||||
if i != n.len - 1: result.add(", ")
|
if i != n.len - 1: result.add ", "
|
||||||
|
|
||||||
proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType =
|
proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType =
|
||||||
case t.kind
|
case t.kind
|
||||||
|
|
@ -2211,17 +2205,11 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
|
||||||
z.callee = arg[i].typ
|
z.callee = arg[i].typ
|
||||||
if tfUnresolved in z.callee.flags: continue
|
if tfUnresolved in z.callee.flags: continue
|
||||||
z.calleeSym = arg[i].sym
|
z.calleeSym = arg[i].sym
|
||||||
#if arg[i].sym.name.s == "cmp":
|
|
||||||
# ggDebug = true
|
|
||||||
# echo "CALLLEEEEEEEE A ", typeToString(z.callee)
|
|
||||||
# XXX this is still all wrong: (T, T) should be 2 generic matches
|
# XXX this is still all wrong: (T, T) should be 2 generic matches
|
||||||
# and (int, int) 2 exact matches, etc. Essentially you cannot call
|
# and (int, int) 2 exact matches, etc. Essentially you cannot call
|
||||||
# typeRel here and expect things to work!
|
# typeRel here and expect things to work!
|
||||||
let r = typeRel(z, f, arg[i].typ)
|
let r = typeRel(z, f, arg[i].typ)
|
||||||
incMatches(z, r, 2)
|
incMatches(z, r, 2)
|
||||||
#if arg[i].sym.name.s == "cmp": # and arg.info.line == 606:
|
|
||||||
# echo "M ", r, " ", arg.info, " ", typeToString(arg[i].sym.typ)
|
|
||||||
# writeMatches(z)
|
|
||||||
if r != isNone:
|
if r != isNone:
|
||||||
z.state = csMatch
|
z.state = csMatch
|
||||||
case x.state
|
case x.state
|
||||||
|
|
@ -2314,14 +2302,7 @@ proc incrIndexType(t: PType) =
|
||||||
template isVarargsUntyped(x): untyped =
|
template isVarargsUntyped(x): untyped =
|
||||||
x.kind == tyVarargs and x[0].kind == tyUntyped
|
x.kind == tyVarargs and x[0].kind == tyUntyped
|
||||||
|
|
||||||
proc matchesAux(c: PContext, n, nOrig: PNode,
|
proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var IntSet) =
|
||||||
m: var TCandidate, marker: var IntSet) =
|
|
||||||
var
|
|
||||||
a = 1 # iterates over the actual given arguments
|
|
||||||
f = if m.callee.kind != tyGenericBody: 1
|
|
||||||
else: 0 # iterates over formal parameters
|
|
||||||
arg: PNode # current prepared argument
|
|
||||||
formal: PSym # current routine parameter
|
|
||||||
|
|
||||||
template noMatch() =
|
template noMatch() =
|
||||||
c.mergeShadowScope #merge so that we don't have to resem for later overloads
|
c.mergeShadowScope #merge so that we don't have to resem for later overloads
|
||||||
|
|
@ -2350,15 +2331,19 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
|
|
||||||
m.state = csMatch # until proven otherwise
|
m.state = csMatch # until proven otherwise
|
||||||
m.firstMismatch = MismatchInfo()
|
m.firstMismatch = MismatchInfo()
|
||||||
m.call = newNodeI(n.kind, n.info)
|
m.call = newNodeIT(n.kind, n.info, m.callee.base)
|
||||||
m.call.typ = base(m.callee) # may be nil
|
|
||||||
var formalLen = m.callee.n.len
|
|
||||||
m.call.add n[0]
|
m.call.add n[0]
|
||||||
var container: PNode = nil # constructed container
|
|
||||||
formal = if formalLen > 1: m.callee.n[1].sym else: nil
|
var
|
||||||
|
a = 1 # iterates over the actual given arguments
|
||||||
|
f = if m.callee.kind != tyGenericBody: 1
|
||||||
|
else: 0 # iterates over formal parameters
|
||||||
|
arg: PNode # current prepared argument
|
||||||
|
formalLen = m.callee.n.len
|
||||||
|
formal = if formalLen > 1: m.callee.n[1].sym else: nil # current routine parameter
|
||||||
|
container: PNode = nil # constructed container
|
||||||
|
|
||||||
while a < n.len:
|
while a < n.len:
|
||||||
|
|
||||||
c.openShadowScope
|
c.openShadowScope
|
||||||
|
|
||||||
if a >= formalLen-1 and f < formalLen and m.callee.n[f].typ.isVarargsUntyped:
|
if a >= formalLen-1 and f < formalLen and m.callee.n[f].typ.isVarargsUntyped:
|
||||||
|
|
@ -2493,7 +2478,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
f = max(f, formalLen - n.len + a + 1)
|
f = max(f, formalLen - n.len + a + 1)
|
||||||
elif formal.typ.kind != tyVarargs or container == nil:
|
elif formal.typ.kind != tyVarargs or container == nil:
|
||||||
setSon(m.call, formal.position + 1, arg)
|
setSon(m.call, formal.position + 1, arg)
|
||||||
inc(f)
|
inc f
|
||||||
container = nil
|
container = nil
|
||||||
else:
|
else:
|
||||||
# we end up here if the argument can be converted into the varargs
|
# we end up here if the argument can be converted into the varargs
|
||||||
|
|
@ -2511,7 +2496,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
else:
|
else:
|
||||||
c.closeShadowScope
|
c.closeShadowScope
|
||||||
|
|
||||||
inc(a)
|
inc a
|
||||||
# for some edge cases (see tdont_return_unowned_from_owned test case)
|
# for some edge cases (see tdont_return_unowned_from_owned test case)
|
||||||
m.firstMismatch.arg = a
|
m.firstMismatch.arg = a
|
||||||
m.firstMismatch.formal = formal
|
m.firstMismatch.formal = formal
|
||||||
|
|
|
||||||
|
|
@ -78,8 +78,7 @@ proc text*(sourceNode: SourceNode, depth: int): string =
|
||||||
result.add(child.node.text(depth + 1))
|
result.add(child.node.text(depth + 1))
|
||||||
|
|
||||||
|
|
||||||
proc `$`*(sourceNode: SourceNode): string =
|
proc `$`*(sourceNode: SourceNode): string = text(sourceNode, 0)
|
||||||
text(sourceNode, 0)
|
|
||||||
|
|
||||||
|
|
||||||
# base64_VLQ
|
# base64_VLQ
|
||||||
|
|
@ -107,8 +106,7 @@ proc encode*(i: int): string =
|
||||||
z += 1
|
z += 1
|
||||||
|
|
||||||
|
|
||||||
type
|
type TokenState = enum Normal, String, Ident, Mangled
|
||||||
TokenState = enum Normal, String, Ident, Mangled
|
|
||||||
|
|
||||||
iterator tokenize*(line: string): (bool, string) =
|
iterator tokenize*(line: string): (bool, string) =
|
||||||
# result = @[]
|
# result = @[]
|
||||||
|
|
@ -244,10 +242,10 @@ proc serializeMappings(map: SourceMapGenerator, mappings: seq[Mapping]): string
|
||||||
var previous = Mapping(generated: (line: 1, column: 0), original: (line: 0, column: 0), name: "", source: "")
|
var previous = Mapping(generated: (line: 1, column: 0), original: (line: 0, column: 0), name: "", source: "")
|
||||||
var previousSourceId = 0
|
var previousSourceId = 0
|
||||||
var previousNameId = 0
|
var previousNameId = 0
|
||||||
result = ""
|
|
||||||
var next = ""
|
var next = ""
|
||||||
var nameId = 0
|
var nameId = 0
|
||||||
var sourceId = 0
|
var sourceId = 0
|
||||||
|
result = ""
|
||||||
|
|
||||||
for z, mapping in mappings:
|
for z, mapping in mappings:
|
||||||
next = ""
|
next = ""
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
# included from sigmatch.nim
|
# included from sigmatch.nim
|
||||||
|
|
||||||
import algorithm, sets, prefixmatches, lineinfos, parseutils, linter
|
import algorithm, sets, prefixmatches, lineinfos, parseutils, linter
|
||||||
from wordrecg import wDeprecated, wError, wAddr, wYield, specialWords
|
from wordrecg import wDeprecated, wError, wAddr, wYield
|
||||||
|
|
||||||
when defined(nimsuggest):
|
when defined(nimsuggest):
|
||||||
import passes, tables, pathutils # importer
|
import passes, tables, pathutils # importer
|
||||||
|
|
|
||||||
|
|
@ -13,44 +13,20 @@ import
|
||||||
strutils, llstream, ast, idents, lexer, options, msgs, parser,
|
strutils, llstream, ast, idents, lexer, options, msgs, parser,
|
||||||
filters, filter_tmpl, renderer, lineinfos, pathutils
|
filters, filter_tmpl, renderer, lineinfos, pathutils
|
||||||
|
|
||||||
type
|
export Parser, parseAll, parseTopLevelStmt, closeParser
|
||||||
TFilterKind* = enum
|
|
||||||
filtNone, filtTemplate, filtReplace, filtStrip
|
|
||||||
TParserKind* = enum
|
|
||||||
skinStandard, skinEndX
|
|
||||||
|
|
||||||
const
|
|
||||||
parserNames*: array[TParserKind, string] = ["standard",
|
|
||||||
"endx"]
|
|
||||||
filterNames*: array[TFilterKind, string] = ["none", "stdtmpl", "replace",
|
|
||||||
"strip"]
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TParsers* = object
|
FilterKind = enum
|
||||||
skin*: TParserKind
|
filtNone = "none"
|
||||||
parser*: TParser
|
filtTemplate = "stdtmpl"
|
||||||
|
filtReplace = "replace"
|
||||||
template config(p: TParsers): ConfigRef = p.parser.lex.config
|
filtStrip = "strip"
|
||||||
|
|
||||||
proc parseAll*(p: var TParsers): PNode =
|
|
||||||
case p.skin
|
|
||||||
of skinStandard:
|
|
||||||
result = parser.parseAll(p.parser)
|
|
||||||
of skinEndX:
|
|
||||||
internalError(p.config, "parser to implement")
|
|
||||||
|
|
||||||
proc parseTopLevelStmt*(p: var TParsers): PNode =
|
|
||||||
case p.skin
|
|
||||||
of skinStandard:
|
|
||||||
result = parser.parseTopLevelStmt(p.parser)
|
|
||||||
of skinEndX:
|
|
||||||
internalError(p.config, "parser to implement")
|
|
||||||
|
|
||||||
proc utf8Bom(s: string): int =
|
proc utf8Bom(s: string): int =
|
||||||
if s.len >= 3 and s[0] == '\xEF' and s[1] == '\xBB' and s[2] == '\xBF':
|
if s.len >= 3 and s[0] == '\xEF' and s[1] == '\xBB' and s[2] == '\xBF':
|
||||||
result = 3
|
3
|
||||||
else:
|
else:
|
||||||
result = 0
|
0
|
||||||
|
|
||||||
proc containsShebang(s: string, i: int): bool =
|
proc containsShebang(s: string, i: int): bool =
|
||||||
if i+1 < s.len and s[i] == '#' and s[i+1] == '!':
|
if i+1 < s.len and s[i] == '#' and s[i+1] == '!':
|
||||||
|
|
@ -78,23 +54,16 @@ proc parsePipe(filename: AbsoluteFile, inputStream: PLLStream; cache: IdentCache
|
||||||
else:
|
else:
|
||||||
inc(i, 2)
|
inc(i, 2)
|
||||||
while i < line.len and line[i] in Whitespace: inc(i)
|
while i < line.len and line[i] in Whitespace: inc(i)
|
||||||
var q: TParser
|
var p: Parser
|
||||||
parser.openParser(q, filename, llStreamOpen(substr(line, i)), cache, config)
|
openParser(p, filename, llStreamOpen(substr(line, i)), cache, config)
|
||||||
result = parser.parseAll(q)
|
result = parseAll(p)
|
||||||
parser.closeParser(q)
|
closeParser(p)
|
||||||
llStreamClose(s)
|
llStreamClose(s)
|
||||||
|
|
||||||
proc getFilter(ident: PIdent): TFilterKind =
|
proc getFilter(ident: PIdent): FilterKind =
|
||||||
for i in low(TFilterKind)..high(TFilterKind):
|
for i in FilterKind:
|
||||||
if cmpIgnoreStyle(ident.s, filterNames[i]) == 0:
|
if cmpIgnoreStyle(ident.s, $i) == 0:
|
||||||
return i
|
return i
|
||||||
result = filtNone
|
|
||||||
|
|
||||||
proc getParser(conf: ConfigRef; n: PNode; ident: PIdent): TParserKind =
|
|
||||||
for i in low(TParserKind)..high(TParserKind):
|
|
||||||
if cmpIgnoreStyle(ident.s, parserNames[i]) == 0:
|
|
||||||
return i
|
|
||||||
localError(conf, n.info, "unknown parser: " & ident.s)
|
|
||||||
|
|
||||||
proc getCallee(conf: ConfigRef; n: PNode): PIdent =
|
proc getCallee(conf: ConfigRef; n: PNode): PIdent =
|
||||||
if n.kind in nkCallKinds and n[0].kind == nkIdent:
|
if n.kind in nkCallKinds and n[0].kind == nkIdent:
|
||||||
|
|
@ -104,30 +73,28 @@ proc getCallee(conf: ConfigRef; n: PNode): PIdent =
|
||||||
else:
|
else:
|
||||||
localError(conf, n.info, "invalid filter: " & renderTree(n))
|
localError(conf, n.info, "invalid filter: " & renderTree(n))
|
||||||
|
|
||||||
proc applyFilter(p: var TParsers, n: PNode, filename: AbsoluteFile,
|
proc applyFilter(p: var Parser, n: PNode, filename: AbsoluteFile,
|
||||||
stdin: PLLStream): PLLStream =
|
stdin: PLLStream): PLLStream =
|
||||||
var ident = getCallee(p.config, n)
|
var f = getFilter(getCallee(p.lex.config, n))
|
||||||
var f = getFilter(ident)
|
result = case f
|
||||||
case f
|
|
||||||
of filtNone:
|
of filtNone:
|
||||||
p.skin = getParser(p.config, n, ident)
|
stdin
|
||||||
result = stdin
|
|
||||||
of filtTemplate:
|
of filtTemplate:
|
||||||
result = filterTmpl(stdin, filename, n, p.config)
|
filterTmpl(p.lex.config, stdin, filename, n)
|
||||||
of filtStrip:
|
of filtStrip:
|
||||||
result = filterStrip(p.config, stdin, filename, n)
|
filterStrip(p.lex.config, stdin, filename, n)
|
||||||
of filtReplace:
|
of filtReplace:
|
||||||
result = filterReplace(p.config, stdin, filename, n)
|
filterReplace(p.lex.config, stdin, filename, n)
|
||||||
if f != filtNone:
|
if f != filtNone:
|
||||||
assert p.config != nil
|
assert p.lex.config != nil
|
||||||
if p.config.hasHint(hintCodeBegin):
|
if p.lex.config.hasHint(hintCodeBegin):
|
||||||
rawMessage(p.config, hintCodeBegin, "")
|
rawMessage(p.lex.config, hintCodeBegin, "")
|
||||||
msgWriteln(p.config, result.s)
|
msgWriteln(p.lex.config, result.s)
|
||||||
rawMessage(p.config, hintCodeEnd, "")
|
rawMessage(p.lex.config, hintCodeEnd, "")
|
||||||
|
|
||||||
proc evalPipe(p: var TParsers, n: PNode, filename: AbsoluteFile,
|
proc evalPipe(p: var Parser, n: PNode, filename: AbsoluteFile,
|
||||||
start: PLLStream): PLLStream =
|
start: PLLStream): PLLStream =
|
||||||
assert p.config != nil
|
assert p.lex.config != nil
|
||||||
result = start
|
result = start
|
||||||
if n.kind == nkEmpty: return
|
if n.kind == nkEmpty: return
|
||||||
if n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.s == "|":
|
if n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.s == "|":
|
||||||
|
|
@ -141,35 +108,28 @@ proc evalPipe(p: var TParsers, n: PNode, filename: AbsoluteFile,
|
||||||
else:
|
else:
|
||||||
result = applyFilter(p, n, filename, result)
|
result = applyFilter(p, n, filename, result)
|
||||||
|
|
||||||
proc openParsers*(p: var TParsers, fileIdx: FileIndex, inputstream: PLLStream;
|
proc openParser*(p: var Parser, fileIdx: FileIndex, inputstream: PLLStream;
|
||||||
cache: IdentCache; config: ConfigRef) =
|
cache: IdentCache; config: ConfigRef) =
|
||||||
assert config != nil
|
assert config != nil
|
||||||
var s: PLLStream
|
|
||||||
p.skin = skinStandard
|
|
||||||
let filename = toFullPathConsiderDirty(config, fileIdx)
|
let filename = toFullPathConsiderDirty(config, fileIdx)
|
||||||
var pipe = parsePipe(filename, inputstream, cache, config)
|
var pipe = parsePipe(filename, inputstream, cache, config)
|
||||||
p.config() = config
|
p.lex.config = config
|
||||||
if pipe != nil: s = evalPipe(p, pipe, filename, inputstream)
|
let s = if pipe != nil: evalPipe(p, pipe, filename, inputstream)
|
||||||
else: s = inputstream
|
else: inputstream
|
||||||
case p.skin
|
parser.openParser(p, fileIdx, s, cache, config)
|
||||||
of skinStandard, skinEndX:
|
|
||||||
parser.openParser(p.parser, fileIdx, s, cache, config)
|
|
||||||
|
|
||||||
proc closeParsers*(p: var TParsers) =
|
proc setupParser*(p: var Parser; fileIdx: FileIndex; cache: IdentCache;
|
||||||
parser.closeParser(p.parser)
|
|
||||||
|
|
||||||
proc setupParsers*(p: var TParsers; fileIdx: FileIndex; cache: IdentCache;
|
|
||||||
config: ConfigRef): bool =
|
config: ConfigRef): bool =
|
||||||
var f: File
|
|
||||||
let filename = toFullPathConsiderDirty(config, fileIdx)
|
let filename = toFullPathConsiderDirty(config, fileIdx)
|
||||||
|
var f: File
|
||||||
if not open(f, filename.string):
|
if not open(f, filename.string):
|
||||||
rawMessage(config, errGenerated, "cannot open file: " & filename.string)
|
rawMessage(config, errGenerated, "cannot open file: " & filename.string)
|
||||||
return false
|
return false
|
||||||
openParsers(p, fileIdx, llStreamOpen(f), cache, config)
|
openParser(p, fileIdx, llStreamOpen(f), cache, config)
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
proc parseFile*(fileIdx: FileIndex; cache: IdentCache; config: ConfigRef): PNode =
|
proc parseFile*(fileIdx: FileIndex; cache: IdentCache; config: ConfigRef): PNode =
|
||||||
var p: TParsers
|
var p: Parser
|
||||||
if setupParsers(p, fileIdx, cache, config):
|
if setupParser(p, fileIdx, cache, config):
|
||||||
result = parseAll(p)
|
result = parseAll(p)
|
||||||
closeParsers(p)
|
closeParser(p)
|
||||||
|
|
|
||||||
|
|
@ -469,9 +469,9 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
prefer
|
prefer
|
||||||
|
|
||||||
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
|
result = ""
|
||||||
let prefer = getPrefer(prefer)
|
let prefer = getPrefer(prefer)
|
||||||
let t = typ
|
let t = typ
|
||||||
result = ""
|
|
||||||
if t == nil: return
|
if t == nil: return
|
||||||
if prefer in preferToResolveSymbols and t.sym != nil and
|
if prefer in preferToResolveSymbols and t.sym != nil and
|
||||||
sfAnon notin t.sym.flags and t.kind != tySequence:
|
sfAnon notin t.sym.flags and t.kind != tySequence:
|
||||||
|
|
|
||||||
|
|
@ -1360,19 +1360,6 @@ proc genMarshalStore(c: PCtx, n: PNode, dest: var TDest) =
|
||||||
c.gABx(n, opcMarshalStore, 0, c.genType(n[1].typ))
|
c.gABx(n, opcMarshalStore, 0, c.genType(n[1].typ))
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
||||||
const
|
|
||||||
atomicTypes = {tyBool, tyChar,
|
|
||||||
tyUntyped, tyTyped, tyTypeDesc, tyStatic,
|
|
||||||
tyEnum,
|
|
||||||
tyOrdinal,
|
|
||||||
tyRange,
|
|
||||||
tyProc,
|
|
||||||
tyPointer, tyOpenArray,
|
|
||||||
tyString, tyCString,
|
|
||||||
tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
|
|
||||||
tyFloat, tyFloat32, tyFloat64, tyFloat128,
|
|
||||||
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64}
|
|
||||||
|
|
||||||
proc unneededIndirection(n: PNode): bool =
|
proc unneededIndirection(n: PNode): bool =
|
||||||
n.typ.skipTypes(abstractInstOwned-{tyTypeDesc}).kind == tyRef
|
n.typ.skipTypes(abstractInstOwned-{tyTypeDesc}).kind == tyRef
|
||||||
|
|
||||||
|
|
@ -2200,7 +2187,7 @@ proc optimizeJumps(c: PCtx; start: int) =
|
||||||
for iters in countdown(maxIterations, 0):
|
for iters in countdown(maxIterations, 0):
|
||||||
case c.code[d].opcode
|
case c.code[d].opcode
|
||||||
of opcJmp:
|
of opcJmp:
|
||||||
d = d + c.code[d].jmpDiff
|
d += c.code[d].jmpDiff
|
||||||
of opcTJmp, opcFJmp:
|
of opcTJmp, opcFJmp:
|
||||||
if c.code[d].regA != reg: break
|
if c.code[d].regA != reg: break
|
||||||
# tjmp x, 23
|
# tjmp x, 23
|
||||||
|
|
@ -2208,12 +2195,12 @@ proc optimizeJumps(c: PCtx; start: int) =
|
||||||
# tjmp x, 12
|
# tjmp x, 12
|
||||||
# -- we know 'x' is true, and so can jump to 12+13:
|
# -- we know 'x' is true, and so can jump to 12+13:
|
||||||
if c.code[d].opcode == opc:
|
if c.code[d].opcode == opc:
|
||||||
d = d + c.code[d].jmpDiff
|
d += c.code[d].jmpDiff
|
||||||
else:
|
else:
|
||||||
# tjmp x, 23
|
# tjmp x, 23
|
||||||
# fjmp x, 22
|
# fjmp x, 22
|
||||||
# We know 'x' is true so skip to the next instruction:
|
# We know 'x' is true so skip to the next instruction:
|
||||||
d = d + 1
|
d += 1
|
||||||
else: break
|
else: break
|
||||||
if d != i + c.code[i].jmpDiff:
|
if d != i + c.code[i].jmpDiff:
|
||||||
c.finalJumpTarget(i, d - i)
|
c.finalJumpTarget(i, d - i)
|
||||||
|
|
@ -2221,7 +2208,7 @@ proc optimizeJumps(c: PCtx; start: int) =
|
||||||
var d = i + c.code[i].jmpDiff
|
var d = i + c.code[i].jmpDiff
|
||||||
var iters = maxIterations
|
var iters = maxIterations
|
||||||
while c.code[d].opcode == opcJmp and iters > 0:
|
while c.code[d].opcode == opcJmp and iters > 0:
|
||||||
d = d + c.code[d].jmpDiff
|
d += c.code[d].jmpDiff
|
||||||
dec iters
|
dec iters
|
||||||
if c.code[d].opcode == opcRet:
|
if c.code[d].opcode == opcRet:
|
||||||
# optimize 'jmp to ret' to 'ret' here
|
# optimize 'jmp to ret' to 'ret' here
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,7 @@ const
|
||||||
wAsm, wBreak, wCase, wConst, wContinue, wDo, wElse, wEnum, wExport,
|
wAsm, wBreak, wCase, wConst, wContinue, wDo, wElse, wEnum, wExport,
|
||||||
wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile, wUsing}
|
wFor, wIf, wReturn, wStatic, wTemplate, wTry, wWhile, wUsing}
|
||||||
|
|
||||||
specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["",
|
specialWords*: array[TSpecialWord, string] = ["",
|
||||||
|
|
||||||
"addr", "and", "as", "asm",
|
"addr", "and", "as", "asm",
|
||||||
"bind", "block", "break", "case", "cast",
|
"bind", "block", "break", "case", "cast",
|
||||||
"concept", "const", "continue", "converter",
|
"concept", "const", "continue", "converter",
|
||||||
|
|
@ -129,35 +128,35 @@ const
|
||||||
|
|
||||||
"immediate", "constructor", "destructor", "delegator", "override",
|
"immediate", "constructor", "destructor", "delegator", "override",
|
||||||
"importcpp", "importobjc",
|
"importcpp", "importobjc",
|
||||||
"importcompilerproc", "importc", "importjs", "exportc", "exportcpp", "exportnims",
|
"importCompilerProc", "importc", "importjs", "exportc", "exportcpp", "exportnims",
|
||||||
"incompletestruct",
|
"incompleteStruct",
|
||||||
"completestruct",
|
"completeStruct",
|
||||||
"requiresinit", "align", "nodecl", "pure", "sideeffect",
|
"requiresInit", "align", "nodecl", "pure", "sideEffect",
|
||||||
"header", "nosideeffect", "gcsafe", "noreturn", "nosinks", "merge", "lib", "dynlib",
|
"header", "noSideEffect", "gcsafe", "noreturn", "nosinks", "merge", "lib", "dynlib",
|
||||||
"compilerproc", "core", "procvar", "base", "used",
|
"compilerproc", "core", "procvar", "base", "used",
|
||||||
"fatal", "error", "warning", "hint", "warningaserror", "line",
|
"fatal", "error", "warning", "hint", "warningAsError", "line",
|
||||||
"push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace",
|
"push", "pop", "define", "undef", "lineDir", "stackTrace", "lineTrace",
|
||||||
"link", "compile", "linksys", "deprecated", "varargs",
|
"link", "compile", "linksys", "deprecated", "varargs",
|
||||||
"callconv", "debugger", "nimcall", "stdcall",
|
"callconv", "debugger", "nimcall", "stdcall",
|
||||||
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "thiscall", "closure",
|
"cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "thiscall", "closure",
|
||||||
"noconv", "on", "off", "checks", "rangechecks", "boundchecks",
|
"noconv", "on", "off", "checks", "rangeChecks", "boundChecks",
|
||||||
"overflowchecks", "nilchecks",
|
"overflowChecks", "nilChecks",
|
||||||
"floatchecks", "nanchecks", "infchecks", "stylechecks", "staticboundchecks",
|
"floatChecks", "nanChecks", "infChecks", "styleChecks", "staticBoundChecks",
|
||||||
"nonreloadable", "executeonreload",
|
"nonReloadable", "executeOnReload",
|
||||||
|
|
||||||
"assertions", "patterns", "trmacros", "sinkinference", "warnings", "hints",
|
"assertions", "patterns", "trmacros", "sinkinference", "warnings", "hints",
|
||||||
"optimization", "raises", "writes", "reads", "size", "effects", "tags",
|
"optimization", "raises", "writes", "reads", "size", "effects", "tags",
|
||||||
"requires", "ensures", "invariant", "assume", "assert",
|
"requires", "ensures", "invariant", "assume", "assert",
|
||||||
"deadcodeelim", # deprecated, dead code elim always happens
|
"deadCodeElim", # deprecated, dead code elim always happens
|
||||||
"safecode", "package", "noforward", "reorder", "norewrite", "nodestroy",
|
"safecode", "package", "noforward", "reorder", "norewrite", "nodestroy",
|
||||||
"pragma",
|
"pragma",
|
||||||
"compiletime", "noinit",
|
"compileTime", "noinit",
|
||||||
"passc", "passl", "localpassc", "borrow", "discardable", "fieldchecks",
|
"passc", "passl", "localPassC", "borrow", "discardable", "fieldChecks",
|
||||||
"subschar", "acyclic", "shallow", "unroll", "linearscanend",
|
"subschar", "acyclic", "shallow", "unroll", "linearScanEnd",
|
||||||
"computedgoto", "injectstmt", "experimental",
|
"computedGoto", "injectStmt", "experimental",
|
||||||
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
|
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
|
||||||
"asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked",
|
"asmNoStackFrame", "implicitStatic", "global", "codegenDecl", "unchecked",
|
||||||
"guard", "locks", "partial", "explain", "liftlocals",
|
"guard", "locks", "partial", "explain", "liftLocals",
|
||||||
|
|
||||||
"auto", "bool", "catch", "char", "class", "compl",
|
"auto", "bool", "catch", "char", "class", "compl",
|
||||||
"const_cast", "default", "delete", "double",
|
"const_cast", "default", "delete", "double",
|
||||||
|
|
@ -184,38 +183,3 @@ proc findStr*(a: openArray[string], s: string): int =
|
||||||
if cmpIgnoreStyle(a[i], s) == 0:
|
if cmpIgnoreStyle(a[i], s) == 0:
|
||||||
return i
|
return i
|
||||||
result = - 1
|
result = - 1
|
||||||
|
|
||||||
proc canonPragmaSpelling*(w: TSpecialWord): string =
|
|
||||||
case w
|
|
||||||
of wNoSideEffect: "noSideEffect"
|
|
||||||
of wImportCompilerProc: "importCompilerProc"
|
|
||||||
of wIncompleteStruct: "incompleteStruct"
|
|
||||||
of wCompleteStruct: "completeStruct"
|
|
||||||
of wRequiresInit: "requiresInit"
|
|
||||||
of wSideEffect: "sideEffect"
|
|
||||||
of wLineDir: "lineDir"
|
|
||||||
of wStackTrace: "stackTrace"
|
|
||||||
of wLineTrace: "lineTrace"
|
|
||||||
of wRangeChecks: "rangeChecks"
|
|
||||||
of wBoundChecks: "boundChecks"
|
|
||||||
of wOverflowChecks: "overflowChecks"
|
|
||||||
of wNilChecks: "nilChecks"
|
|
||||||
of wFloatChecks: "floatChecks"
|
|
||||||
of wNanChecks: "nanChecks"
|
|
||||||
of wInfChecks: "infChecks"
|
|
||||||
of wStyleChecks: "styleChecks"
|
|
||||||
of wNonReloadable: "nonReloadable"
|
|
||||||
of wExecuteOnReload: "executeOnReload"
|
|
||||||
of wDeadCodeElimUnused: "deadCodeElim"
|
|
||||||
of wCompileTime: "compileTime"
|
|
||||||
of wFieldChecks: "fieldChecks"
|
|
||||||
of wLinearScanEnd: "linearScanEnd"
|
|
||||||
of wComputedGoto: "computedGoto"
|
|
||||||
of wInjectStmt: "injectStmt"
|
|
||||||
of wAsmNoStackFrame: "asmNoStackFrame"
|
|
||||||
of wImplicitStatic: "implicitStatic"
|
|
||||||
of wCodegenDecl: "codegenDecl"
|
|
||||||
of wLiftLocals: "liftLocals"
|
|
||||||
of wLocalPassc: "localPassc"
|
|
||||||
of wWarningAsError: "warningAsError"
|
|
||||||
else: specialWords[w]
|
|
||||||
|
|
|
||||||
|
|
@ -54,12 +54,12 @@ proc prettyPrint(infile, outfile: string, opt: PrettyOptions) =
|
||||||
let f = splitFile(outfile.expandTilde)
|
let f = splitFile(outfile.expandTilde)
|
||||||
conf.outFile = RelativeFile f.name & f.ext
|
conf.outFile = RelativeFile f.name & f.ext
|
||||||
conf.outDir = toAbsoluteDir f.dir
|
conf.outDir = toAbsoluteDir f.dir
|
||||||
var p: TParsers
|
var parser: Parser
|
||||||
p.parser.em.indWidth = opt.indWidth
|
parser.em.indWidth = opt.indWidth
|
||||||
if setupParsers(p, fileIdx, newIdentCache(), conf):
|
if setupParser(parser, fileIdx, newIdentCache(), conf):
|
||||||
p.parser.em.maxLineLen = opt.maxLineLen
|
parser.em.maxLineLen = opt.maxLineLen
|
||||||
discard parseAll(p)
|
discard parseAll(parser)
|
||||||
closeParsers(p)
|
closeParser(parser)
|
||||||
|
|
||||||
proc main =
|
proc main =
|
||||||
var outfile, outdir: string
|
var outfile, outdir: string
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ proc checkGrammarFileImpl(cache: IdentCache, config: ConfigRef) =
|
||||||
if stream != nil:
|
if stream != nil:
|
||||||
declaredSyms.incl "section" # special case for 'section(RULE)' in the grammar
|
declaredSyms.incl "section" # special case for 'section(RULE)' in the grammar
|
||||||
var
|
var
|
||||||
L: TLexer
|
L: Lexer
|
||||||
tok: TToken
|
tok: Token
|
||||||
initToken(tok)
|
initToken(tok)
|
||||||
openLexer(L, f, stream, cache, config)
|
openLexer(L, f, stream, cache, config)
|
||||||
# load the first token:
|
# load the first token:
|
||||||
|
|
|
||||||
|
|
@ -195,8 +195,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; conf: ConfigRef) =
|
||||||
of cmdArgument:
|
of cmdArgument:
|
||||||
let info = p.key.split(':')
|
let info = p.key.split(':')
|
||||||
if info.len == 3:
|
if info.len == 3:
|
||||||
let (dir, file, ext) = info[0].splitFile()
|
conf.projectName = findProjectNimFile(conf, info[0].splitFile.dir)
|
||||||
conf.projectName = findProjectNimFile(conf, dir)
|
|
||||||
if conf.projectName.len == 0: conf.projectName = info[0]
|
if conf.projectName.len == 0: conf.projectName = info[0]
|
||||||
try:
|
try:
|
||||||
conf.m.trackPos = newLineInfo(conf, AbsoluteFile info[0],
|
conf.m.trackPos = newLineInfo(conf, AbsoluteFile info[0],
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue