remove more global variables in the Nim compiler

This commit is contained in:
Andreas Rumpf 2018-05-27 11:10:56 +02:00
commit 669a564492
77 changed files with 679 additions and 679 deletions

View file

@ -10,7 +10,7 @@
# abstract syntax tree + symbol table # abstract syntax tree + symbol table
import import
msgs, hashes, nversion, options, strutils, std / sha1, ropes, idents, lineinfos, hashes, nversion, options, strutils, std / sha1, ropes, idents,
intsets, idgen intsets, idgen
type type

View file

@ -12,7 +12,8 @@
# the data structures here are used in various places of the compiler. # the data structures here are used in various places of the compiler.
import import
ast, hashes, intsets, strutils, options, msgs, ropes, idents, rodutils ast, hashes, intsets, strutils, options, lineinfos, ropes, idents, rodutils,
msgs
proc hashNode*(p: RootRef): Hash proc hashNode*(p: RootRef): Hash
proc treeToYaml*(conf: ConfigRef; n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope proc treeToYaml*(conf: ConfigRef; n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope
@ -23,44 +24,6 @@ proc typeToYaml*(conf: ConfigRef; n: PType, indent: int = 0, maxRecDepth: int =
proc symToYaml*(conf: ConfigRef; n: PSym, indent: int = 0, maxRecDepth: int = - 1): Rope proc symToYaml*(conf: ConfigRef; n: PSym, indent: int = 0, maxRecDepth: int = - 1): Rope
proc lineInfoToStr*(conf: ConfigRef; info: TLineInfo): Rope proc lineInfoToStr*(conf: ConfigRef; info: TLineInfo): Rope
# ----------------------- node sets: ---------------------------------------
proc objectSetContains*(t: TObjectSet, obj: RootRef): bool
# returns true whether n is in t
proc objectSetIncl*(t: var TObjectSet, obj: RootRef)
# include an element n in the table t
proc objectSetContainsOrIncl*(t: var TObjectSet, obj: RootRef): bool
# more are not needed ...
# ----------------------- str table -----------------------------------------
proc strTableContains*(t: TStrTable, n: PSym): bool
proc strTableAdd*(t: var TStrTable, n: PSym)
proc strTableGet*(t: TStrTable, name: PIdent): PSym
type
TTabIter*{.final.} = object # consider all fields here private
h*: Hash # current hash
proc initTabIter*(ti: var TTabIter, tab: TStrTable): PSym
proc nextIter*(ti: var TTabIter, tab: TStrTable): PSym
# usage:
# var
# i: TTabIter
# s: PSym
# s = InitTabIter(i, table)
# while s != nil:
# ...
# s = NextIter(i, table)
#
type
TIdentIter*{.final.} = object # iterator over all syms with same identifier
h*: Hash # current hash
name*: PIdent
proc initIdentIter*(ti: var TIdentIter, tab: TStrTable, s: PIdent): PSym
proc nextIdentIter*(ti: var TIdentIter, tab: TStrTable): PSym
when declared(echo): when declared(echo):
# these are for debugging only: They are not really deprecated, but I want # these are for debugging only: They are not really deprecated, but I want
# the warning so that release versions do not contain debugging statements: # the warning so that release versions do not contain debugging statements:
@ -470,7 +433,7 @@ proc nextTry(h, maxHash: Hash): Hash =
# generates each int in range(maxHash) exactly once (see any text on # generates each int in range(maxHash) exactly once (see any text on
# random-number generation for proof). # random-number generation for proof).
proc objectSetContains(t: TObjectSet, obj: RootRef): bool = proc objectSetContains*(t: TObjectSet, obj: RootRef): bool =
# returns true whether n is in t # returns true whether n is in t
var h: Hash = hashNode(obj) and high(t.data) # start with real hash value var h: Hash = hashNode(obj) and high(t.data) # start with real hash value
while t.data[h] != nil: while t.data[h] != nil:
@ -494,12 +457,12 @@ proc objectSetEnlarge(t: var TObjectSet) =
if t.data[i] != nil: objectSetRawInsert(n, t.data[i]) if t.data[i] != nil: objectSetRawInsert(n, t.data[i])
swap(t.data, n) swap(t.data, n)
proc objectSetIncl(t: var TObjectSet, obj: RootRef) = proc objectSetIncl*(t: var TObjectSet, obj: RootRef) =
if mustRehash(len(t.data), t.counter): objectSetEnlarge(t) if mustRehash(len(t.data), t.counter): objectSetEnlarge(t)
objectSetRawInsert(t.data, obj) objectSetRawInsert(t.data, obj)
inc(t.counter) inc(t.counter)
proc objectSetContainsOrIncl(t: var TObjectSet, obj: RootRef): bool = proc objectSetContainsOrIncl*(t: var TObjectSet, obj: RootRef): bool =
# returns true if obj is already in the string table: # returns true if obj is already in the string table:
var h: Hash = hashNode(obj) and high(t.data) var h: Hash = hashNode(obj) and high(t.data)
while true: while true:
@ -517,7 +480,7 @@ proc objectSetContainsOrIncl(t: var TObjectSet, obj: RootRef): bool =
inc(t.counter) inc(t.counter)
result = false result = false
proc strTableContains(t: TStrTable, n: PSym): bool = proc strTableContains*(t: TStrTable, n: PSym): bool =
var h: Hash = n.name.h and high(t.data) # start with real hash value var h: Hash = n.name.h and high(t.data) # start with real hash value
while t.data[h] != nil: while t.data[h] != nil:
if (t.data[h] == n): if (t.data[h] == n):
@ -573,7 +536,7 @@ proc strTableEnlarge(t: var TStrTable) =
if t.data[i] != nil: strTableRawInsert(n, t.data[i]) if t.data[i] != nil: strTableRawInsert(n, t.data[i])
swap(t.data, n) swap(t.data, n)
proc strTableAdd(t: var TStrTable, n: PSym) = proc strTableAdd*(t: var TStrTable, n: PSym) =
if mustRehash(len(t.data), t.counter): strTableEnlarge(t) if mustRehash(len(t.data), t.counter): strTableEnlarge(t)
strTableRawInsert(t.data, n) strTableRawInsert(t.data, n)
inc(t.counter) inc(t.counter)
@ -609,7 +572,7 @@ proc strTableIncl*(t: var TStrTable, n: PSym; onConflictKeepOld=false): bool {.d
inc(t.counter) inc(t.counter)
result = false result = false
proc strTableGet(t: TStrTable, name: PIdent): PSym = proc strTableGet*(t: TStrTable, name: PIdent): PSym =
var h: Hash = name.h and high(t.data) var h: Hash = name.h and high(t.data)
while true: while true:
result = t.data[h] result = t.data[h]
@ -617,13 +580,13 @@ proc strTableGet(t: TStrTable, name: PIdent): PSym =
if result.name.id == name.id: break if result.name.id == name.id: break
h = nextTry(h, high(t.data)) h = nextTry(h, high(t.data))
proc initIdentIter(ti: var TIdentIter, tab: TStrTable, s: PIdent): PSym =
ti.h = s.h
ti.name = s
if tab.counter == 0: result = nil
else: result = nextIdentIter(ti, tab)
proc nextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym = type
TIdentIter* = object # iterator over all syms with same identifier
h*: Hash # current hash
name*: PIdent
proc nextIdentIter*(ti: var TIdentIter, tab: TStrTable): PSym =
var h = ti.h and high(tab.data) var h = ti.h and high(tab.data)
var start = h var start = h
result = tab.data[h] result = tab.data[h]
@ -636,6 +599,12 @@ proc nextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym =
result = tab.data[h] result = tab.data[h]
ti.h = nextTry(h, high(tab.data)) ti.h = nextTry(h, high(tab.data))
proc initIdentIter*(ti: var TIdentIter, tab: TStrTable, s: PIdent): PSym =
ti.h = s.h
ti.name = s
if tab.counter == 0: result = nil
else: result = nextIdentIter(ti, tab)
proc nextIdentExcluding*(ti: var TIdentIter, tab: TStrTable, proc nextIdentExcluding*(ti: var TIdentIter, tab: TStrTable,
excluding: IntSet): PSym = excluding: IntSet): PSym =
var h: Hash = ti.h and high(tab.data) var h: Hash = ti.h and high(tab.data)
@ -659,20 +628,33 @@ proc firstIdentExcluding*(ti: var TIdentIter, tab: TStrTable, s: PIdent,
if tab.counter == 0: result = nil if tab.counter == 0: result = nil
else: result = nextIdentExcluding(ti, tab, excluding) else: result = nextIdentExcluding(ti, tab, excluding)
proc initTabIter(ti: var TTabIter, tab: TStrTable): PSym = type
ti.h = 0 # we start by zero ... TTabIter* = object
if tab.counter == 0: h: Hash
result = nil # FIX 1: removed endless loop
else:
result = nextIter(ti, tab)
proc nextIter(ti: var TTabIter, tab: TStrTable): PSym = proc nextIter*(ti: var TTabIter, tab: TStrTable): PSym =
# usage:
# var
# i: TTabIter
# s: PSym
# s = InitTabIter(i, table)
# while s != nil:
# ...
# s = NextIter(i, table)
#
result = nil result = nil
while (ti.h <= high(tab.data)): while (ti.h <= high(tab.data)):
result = tab.data[ti.h] result = tab.data[ti.h]
inc(ti.h) # ... and increment by one always inc(ti.h) # ... and increment by one always
if result != nil: break if result != nil: break
proc initTabIter*(ti: var TTabIter, tab: TStrTable): PSym =
ti.h = 0
if tab.counter == 0:
result = nil
else:
result = nextIter(ti, tab)
iterator items*(tab: TStrTable): PSym = iterator items*(tab: TStrTable): PSym =
var it: TTabIter var it: TTabIter
var s = initTabIter(it, tab) var s = initTabIter(it, tab)

View file

@ -57,7 +57,7 @@ template getUniqueType*(key: PType): PType = key
proc makeSingleLineCString*(s: string): string = proc makeSingleLineCString*(s: string): string =
result = "\"" result = "\""
for c in items(s): for c in items(s):
result.add(c.toCChar) c.toCChar(result)
result.add('\"') result.add('\"')
proc mangle*(name: string): string = proc mangle*(name: string): string =

View file

@ -14,12 +14,12 @@ import
nversion, nimsets, msgs, std / sha1, bitsets, idents, types, nversion, nimsets, msgs, std / sha1, bitsets, idents, types,
ccgutils, os, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, ccgutils, os, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
lowerings, semparallel, tables, sets, ndi lowerings, semparallel, tables, sets, ndi, lineinfos
import strutils except `%` # collides with ropes.`%` import strutils except `%` # collides with ropes.`%`
from modulegraphs import ModuleGraph from modulegraphs import ModuleGraph
from configuration import from lineinfos import
warnGcMem, errXMustBeCompileTime, hintDependency, errGenerated, errCannotOpenFile warnGcMem, errXMustBeCompileTime, hintDependency, errGenerated, errCannotOpenFile
import dynlib import dynlib
@ -949,8 +949,8 @@ proc getFileHeader(conf: ConfigRef; cfile: Cfile): Rope =
proc genFilenames(m: BModule): Rope = proc genFilenames(m: BModule): Rope =
discard cgsym(m, "dbgRegisterFilename") discard cgsym(m, "dbgRegisterFilename")
result = nil result = nil
for i in 0..<fileInfos.len: for i in 0..<m.config.m.fileInfos.len:
result.addf("dbgRegisterFilename($1);$N", [fileInfos[i].projPath.makeCString]) result.addf("dbgRegisterFilename($1);$N", [m.config.m.fileInfos[i].projPath.makeCString])
proc genMainProc(m: BModule) = proc genMainProc(m: BModule) =
const const

View file

@ -11,9 +11,8 @@
import import
ast, astalgo, ropes, passes, options, intsets, platform, sighashes, ast, astalgo, ropes, passes, options, intsets, platform, sighashes,
tables, ndi tables, ndi, lineinfos
from msgs import TLineInfo
from modulegraphs import ModuleGraph from modulegraphs import ModuleGraph
type type

View file

@ -11,7 +11,7 @@
import import
intsets, options, ast, astalgo, msgs, idents, renderer, types, magicsys, intsets, options, ast, astalgo, msgs, idents, renderer, types, magicsys,
sempass2, strutils, modulegraphs, configuration sempass2, strutils, modulegraphs, lineinfos
proc genConv(n: PNode, d: PType, downcast: bool; conf: ConfigRef): PNode = proc genConv(n: PNode, d: PType, downcast: bool; conf: ConfigRef): PNode =
var dest = skipTypes(d, abstractPtrs) var dest = skipTypes(d, abstractPtrs)

View file

@ -26,7 +26,7 @@ bootSwitch(usedNoGC, defined(nogc), "--gc:none")
import import
os, msgs, options, nversion, condsyms, strutils, extccomp, platform, os, msgs, options, nversion, condsyms, strutils, extccomp, platform,
wordrecg, parseutils, nimblecmd, idents, parseopt, sequtils, configuration wordrecg, parseutils, nimblecmd, idents, parseopt, sequtils, lineinfos
# but some have deps to imported modules. Yay. # but some have deps to imported modules. Yay.
bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc") bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc")
@ -178,11 +178,11 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
if i < len(arg) and (arg[i] in {':', '='}): inc(i) if i < len(arg) and (arg[i] in {':', '='}): inc(i)
else: invalidCmdLineOption(conf, pass, orig, info) else: invalidCmdLineOption(conf, pass, orig, info)
if state == wHint: if state == wHint:
let x = findStr(configuration.HintsToStr, id) let x = findStr(lineinfos.HintsToStr, id)
if x >= 0: n = TNoteKind(x + ord(hintMin)) if x >= 0: n = TNoteKind(x + ord(hintMin))
else: localError(conf, info, "unknown hint: " & id) else: localError(conf, info, "unknown hint: " & id)
else: else:
let x = findStr(configuration.WarningsToStr, id) let x = findStr(lineinfos.WarningsToStr, id)
if x >= 0: n = TNoteKind(x + ord(warnMin)) if x >= 0: n = TNoteKind(x + ord(warnMin))
else: localError(conf, info, "unknown warning: " & id) else: localError(conf, info, "unknown warning: " & id)
case substr(arg, i).normalize case substr(arg, i).normalize
@ -324,7 +324,7 @@ proc trackDirty(conf: ConfigRef; arg: string, info: TLineInfo) =
if dirtyOriginalIdx.int32 >= 0: if dirtyOriginalIdx.int32 >= 0:
msgs.setDirtyFile(conf, dirtyOriginalIdx, a[0]) msgs.setDirtyFile(conf, dirtyOriginalIdx, a[0])
gTrackPos = newLineInfo(dirtyOriginalIdx, line, column) conf.m.trackPos = newLineInfo(dirtyOriginalIdx, line, column)
proc track(conf: ConfigRef; arg: string, info: TLineInfo) = proc track(conf: ConfigRef; arg: string, info: TLineInfo) =
var a = arg.split(',') var a = arg.split(',')
@ -334,7 +334,7 @@ proc track(conf: ConfigRef; arg: string, info: TLineInfo) =
localError(conf, info, errInvalidNumber % a[1]) localError(conf, info, errInvalidNumber % a[1])
if parseUtils.parseInt(a[2], column) <= 0: if parseUtils.parseInt(a[2], column) <= 0:
localError(conf, info, errInvalidNumber % a[2]) localError(conf, info, errInvalidNumber % a[2])
gTrackPos = newLineInfo(conf, a[0], line, column) conf.m.trackPos = newLineInfo(conf, a[0], line, column)
proc dynlibOverride(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = proc dynlibOverride(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
if pass in {passCmd2, passPP}: if pass in {passCmd2, passPP}:

View file

@ -1,182 +1,6 @@
# ## Use the module 'lineinfos' instead!
#
# The Nim Compiler
# (c) Copyright 2018 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module contains the rather excessive configuration object that {.deprecated.}
## needs to be passed around to everything so that the compiler becomes
## more useful as a library.
const import lineinfos
explanationsBaseUrl* = "https://nim-lang.org/docs/manual" export lineinfos
type
TMsgKind* = enum
errUnknown, errInternal, errIllFormedAstX, errCannotOpenFile,
errXExpected,
errGridTableNotImplemented,
errGeneralParseError,
errNewSectionExpected,
errInvalidDirectiveX,
errGenerated,
errUser,
warnCannotOpenFile,
warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit,
warnDeprecated, warnConfigDeprecated,
warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel,
warnUnknownSubstitutionX, warnLanguageXNotSupported,
warnFieldXNotSupported, warnCommentXIgnored,
warnTypelessParam,
warnUseBase, warnWriteToForeignHeap, warnUnsafeCode,
warnEachIdentIsTuple, warnShadowIdent,
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
warnInconsistentSpacing, warnUser,
hintSuccess, hintSuccessX,
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
hintConditionAlwaysTrue, hintName, hintPattern,
hintExecuting, hintLinking, hintDependency,
hintSource, hintPerformance, hintStackTrace, hintGCStats,
hintUser, hintUserRaw
const
MsgKindToStr*: array[TMsgKind, string] = [
errUnknown: "unknown error",
errInternal: "internal error: $1",
errIllFormedAstX: "illformed AST: $1",
errCannotOpenFile: "cannot open '$1'",
errXExpected: "'$1' expected",
errGridTableNotImplemented: "grid table is not implemented",
errGeneralParseError: "general parse error",
errNewSectionExpected: "new section expected",
errInvalidDirectiveX: "invalid directive: '$1'",
errGenerated: "$1",
errUser: "$1",
warnCannotOpenFile: "cannot open '$1'",
warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored",
warnXIsNeverRead: "'$1' is never read",
warnXmightNotBeenInit: "'$1' might not have been initialized",
warnDeprecated: "$1 is deprecated",
warnConfigDeprecated: "config file '$1' is deprecated",
warnSmallLshouldNotBeUsed: "'l' should not be used as an identifier; may look like '1' (one)",
warnUnknownMagic: "unknown magic '$1' might crash the compiler",
warnRedefinitionOfLabel: "redefinition of label '$1'",
warnUnknownSubstitutionX: "unknown substitution '$1'",
warnLanguageXNotSupported: "language '$1' not supported",
warnFieldXNotSupported: "field '$1' not supported",
warnCommentXIgnored: "comment '$1' ignored",
warnTypelessParam: "'$1' has no type. Typeless parameters are deprecated; only allowed for 'template'",
warnUseBase: "use {.base.} for base methods; baseless methods are deprecated",
warnWriteToForeignHeap: "write to foreign heap",
warnUnsafeCode: "unsafe code: '$1'",
warnEachIdentIsTuple: "each identifier is a tuple",
warnShadowIdent: "shadowed identifier: '$1'",
warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.",
warnProveField: "cannot prove that field '$1' is accessible",
warnProveIndex: "cannot prove index '$1' is valid",
warnGcUnsafe: "not GC-safe: '$1'",
warnGcUnsafe2: "$1",
warnUninit: "'$1' might not have been initialized",
warnGcMem: "'$1' uses GC'ed memory",
warnDestructor: "usage of a type with a destructor in a non destructible context. This will become a compile time error in the future.",
warnLockLevel: "$1",
warnResultShadowed: "Special variable 'result' is shadowed.",
warnInconsistentSpacing: "Number of spaces around '$#' is not consistent",
warnUser: "$1",
hintSuccess: "operation successful",
hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#; $#)",
hintLineTooLong: "line too long",
hintXDeclaredButNotUsed: "'$1' is declared but not used",
hintConvToBaseNotNeeded: "conversion to base object is not needed",
hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless",
hintExprAlwaysX: "expression evaluates always to '$1'",
hintQuitCalled: "quit() called",
hintProcessing: "$1",
hintCodeBegin: "generated code listing:",
hintCodeEnd: "end of listing",
hintConf: "used config file '$1'",
hintPath: "added path: '$1'",
hintConditionAlwaysTrue: "condition is always true: '$1'",
hintName: "name should be: '$1'",
hintPattern: "$1",
hintExecuting: "$1",
hintLinking: "",
hintDependency: "$1",
hintSource: "$1",
hintPerformance: "$1",
hintStackTrace: "$1",
hintGCStats: "$1",
hintUser: "$1",
hintUserRaw: "$1"]
const
WarningsToStr* = ["CannotOpenFile", "OctalEscape",
"XIsNeverRead", "XmightNotBeenInit",
"Deprecated", "ConfigDeprecated",
"SmallLshouldNotBeUsed", "UnknownMagic",
"RedefinitionOfLabel", "UnknownSubstitutionX",
"LanguageXNotSupported", "FieldXNotSupported",
"CommentXIgnored",
"TypelessParam", "UseBase", "WriteToForeignHeap",
"UnsafeCode", "EachIdentIsTuple", "ShadowIdent",
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
"GcMem", "Destructor", "LockLevel", "ResultShadowed",
"Spacing", "User"]
HintsToStr* = ["Success", "SuccessX", "LineTooLong",
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
"Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency",
"Source", "Performance", "StackTrace", "GCStats",
"User", "UserRaw"]
const
fatalMin* = errUnknown
fatalMax* = errInternal
errMin* = errUnknown
errMax* = errUser
warnMin* = warnCannotOpenFile
warnMax* = pred(hintSuccess)
hintMin* = hintSuccess
hintMax* = high(TMsgKind)
static:
doAssert HintsToStr.len == ord(hintMax) - ord(hintMin) + 1
doAssert WarningsToStr.len == ord(warnMax) - ord(warnMin) + 1
type
TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints
TNoteKinds* = set[TNoteKind]
const
NotesVerbosity*: array[0..3, TNoteKinds] = [
{low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent, warnUninit,
warnProveField, warnProveIndex,
warnGcUnsafe,
hintSuccessX, hintPath, hintConf,
hintProcessing, hintPattern,
hintDependency,
hintExecuting, hintLinking,
hintCodeBegin, hintCodeEnd,
hintSource, hintStackTrace,
hintGCStats},
{low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent, warnUninit,
warnProveField, warnProveIndex,
warnGcUnsafe,
hintPath,
hintDependency,
hintCodeBegin, hintCodeEnd,
hintSource, hintStackTrace,
hintGCStats},
{low(TNoteKind)..high(TNoteKind)} - {hintStackTrace, warnUninit},
{low(TNoteKind)..high(TNoteKind)}]
const
errXMustBeCompileTime* = "'$1' can only be used in compile-time context"
errArgsNeedRunOption* = "arguments can only be given if the '--run' option is selected"

View file

@ -117,7 +117,7 @@ Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently
import import
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
strutils, options, dfa, lowerings, rodread, tables, modulegraphs, strutils, options, dfa, lowerings, rodread, tables, modulegraphs,
configuration lineinfos
const const
InterestingSyms = {skVar, skResult, skLet} InterestingSyms = {skVar, skResult, skLet}

View file

@ -23,7 +23,7 @@
## "A Graph–Free Approach to Data–Flow Analysis" by Markus Mohnen. ## "A Graph–Free Approach to Data–Flow Analysis" by Markus Mohnen.
## https://link.springer.com/content/pdf/10.1007/3-540-45937-5_6.pdf ## https://link.springer.com/content/pdf/10.1007/3-540-45937-5_6.pdf
import ast, astalgo, types, intsets, tables, msgs, options import ast, astalgo, types, intsets, tables, msgs, options, lineinfos
type type
InstrKind* = enum InstrKind* = enum

View file

@ -16,7 +16,7 @@ import
wordrecg, syntaxes, renderer, lexer, packages/docutils/rstast, wordrecg, syntaxes, renderer, lexer, packages/docutils/rstast,
packages/docutils/rst, packages/docutils/rstgen, times, packages/docutils/rst, packages/docutils/rstgen, times,
packages/docutils/highlite, sempass2, json, xmltree, cgi, packages/docutils/highlite, sempass2, json, xmltree, cgi,
typesrenderer, astalgo, modulepaths, configuration typesrenderer, astalgo, modulepaths, lineinfos
type type
TSections = array[TSymKind, Rope] TSections = array[TSymKind, Rope]

View file

@ -11,7 +11,7 @@
# semantic checking. # semantic checking.
import import
os, options, ast, astalgo, msgs, ropes, idents, passes, docgen os, options, ast, astalgo, msgs, ropes, idents, passes, docgen, lineinfos
from modulegraphs import ModuleGraph from modulegraphs import ModuleGraph

View file

@ -11,7 +11,7 @@
import import
strutils, options, ast, astalgo, msgs, os, idents, wordrecg, renderer, strutils, options, ast, astalgo, msgs, os, idents, wordrecg, renderer,
rodread rodread, lineinfos
type type
TemplCtx = object TemplCtx = object
@ -114,7 +114,6 @@ proc evalTemplateArgs(n: PNode, s: PSym; conf: ConfigRef; fromHlo: bool): PNode
# to prevent endless recursion in template instantiation # to prevent endless recursion in template instantiation
const evalTemplateLimit* = 1000 const evalTemplateLimit* = 1000
var evalTemplateCounter* = 0 # XXX remove this global
proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode = proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
when true: when true:
@ -140,8 +139,8 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
conf: ConfigRef; fromHlo=false): PNode = conf: ConfigRef; fromHlo=false): PNode =
inc(evalTemplateCounter) inc(conf.evalTemplateCounter)
if evalTemplateCounter > evalTemplateLimit: if conf.evalTemplateCounter > evalTemplateLimit:
globalError(conf, n.info, errTemplateInstantiationTooNested) globalError(conf, n.info, errTemplateInstantiationTooNested)
result = n result = n
@ -170,5 +169,5 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
evalTemplateAux(body.sons[i], args, ctx, result) evalTemplateAux(body.sons[i], args, ctx, result)
result.flags.incl nfFromTemplate result.flags.incl nfFromTemplate
result = wrapInComesFrom(n.info, tmpl, result) result = wrapInComesFrom(n.info, tmpl, result)
dec(evalTemplateCounter) dec(conf.evalTemplateCounter)

View file

@ -9,12 +9,12 @@
# Module providing functions for calling the different external C compilers # Module providing functions for calling the different external C compilers
# Uses some hard-wired facts about each C/C++ compiler, plus options read # Uses some hard-wired facts about each C/C++ compiler, plus options read
# from a configuration file, to provide generalized procedures to compile # from a lineinfos file, to provide generalized procedures to compile
# nim files. # nim files.
import import
ropes, os, strutils, osproc, platform, condsyms, options, msgs, ropes, os, strutils, osproc, platform, condsyms, options, msgs,
configuration, std / sha1, streams lineinfos, std / sha1, streams
type type
TInfoCCProp* = enum # properties of the C compiler: TInfoCCProp* = enum # properties of the C compiler:

View file

@ -11,7 +11,7 @@
import import
llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options, llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
renderer, filters renderer, filters, lineinfos
type type
TParseState = enum TParseState = enum

View file

@ -9,7 +9,8 @@
## Module that implements ``gorge`` for the compiler. ## Module that implements ``gorge`` for the compiler.
import msgs, std / sha1, os, osproc, streams, strutils, options import msgs, std / sha1, os, osproc, streams, strutils, options,
lineinfos
proc readOutput(p: Process): (string, int) = proc readOutput(p: Process): (string, int) =
result[0] = "" result[0] = ""

View file

@ -10,7 +10,7 @@
## This module implements the 'implies' relation for guards. ## This module implements the 'implies' relation for guards.
import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer, idents, import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer, idents,
saturate, modulegraphs, options, configuration saturate, modulegraphs, options, lineinfos
const const
someEq = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc, someEq = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,

View file

@ -43,8 +43,8 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
if not isNil(x): if not isNil(x):
assert x.kind in {nkStmtList, nkCall} assert x.kind in {nkStmtList, nkCall}
# better be safe than sorry, so check evalTemplateCounter too: # better be safe than sorry, so check evalTemplateCounter too:
inc(evalTemplateCounter) inc(c.config.evalTemplateCounter)
if evalTemplateCounter > evalTemplateLimit: if c.config.evalTemplateCounter > evalTemplateLimit:
globalError(c.config, n.info, "template instantiation too nested") globalError(c.config, n.info, "template instantiation too nested")
# deactivate this pattern: # deactivate this pattern:
c.patterns[i] = nil c.patterns[i] = nil
@ -54,7 +54,7 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
result = flattenStmts(x) result = flattenStmts(x)
else: else:
result = evalPattern(c, x, result) result = evalPattern(c, x, result)
dec(evalTemplateCounter) dec(c.config.evalTemplateCounter)
# activate this pattern again: # activate this pattern again:
c.patterns[i] = pattern c.patterns[i] = pattern

View file

@ -11,7 +11,7 @@
import import
intsets, strutils, os, ast, astalgo, msgs, options, idents, rodread, lookups, intsets, strutils, os, ast, astalgo, msgs, options, idents, rodread, lookups,
semdata, passes, renderer, modulepaths, sigmatch, configuration semdata, passes, renderer, modulepaths, sigmatch, lineinfos
proc evalImport*(c: PContext, n: PNode): PNode proc evalImport*(c: PContext, n: PNode): PNode
proc evalFrom*(c: PContext, n: PNode): PNode proc evalFrom*(c: PContext, n: PNode): PNode

View file

@ -32,7 +32,7 @@ import
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options, ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options,
nversion, nimsets, msgs, std / sha1, bitsets, idents, types, os, tables, nversion, nimsets, msgs, std / sha1, bitsets, idents, types, os, tables,
times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils, times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils,
intsets, cgmeth, lowerings, sighashes, configuration intsets, cgmeth, lowerings, sighashes, lineinfos
from modulegraphs import ModuleGraph from modulegraphs import ModuleGraph

View file

@ -12,7 +12,7 @@
import import
intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os, intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os,
idents, renderer, types, magicsys, rodread, lowerings, tables, idents, renderer, types, magicsys, rodread, lowerings, tables,
modulegraphs modulegraphs, lineinfos
discard """ discard """
The basic approach is that captured vars need to be put on the heap and The basic approach is that captured vars need to be put on the heap and

View file

@ -17,7 +17,7 @@
import import
hashes, options, msgs, strutils, platform, idents, nimlexbase, llstream, hashes, options, msgs, strutils, platform, idents, nimlexbase, llstream,
wordrecg, configuration wordrecg, lineinfos
const const
MaxLineLength* = 80 # lines longer than this lead to a warning MaxLineLength* = 80 # lines longer than this lead to a warning
@ -273,10 +273,10 @@ template tokenBegin(tok, pos) {.dirty.} =
template tokenEnd(tok, pos) {.dirty.} = template tokenEnd(tok, pos) {.dirty.} =
when defined(nimsuggest): when defined(nimsuggest):
let colB = getColNumber(L, pos)+1 let colB = getColNumber(L, pos)+1
if L.fileIdx == gTrackPos.fileIndex and gTrackPos.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 == gTrackPos.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.cursor = CursorPosition.InToken
gTrackPos.col = colA.int16 L.config.m.trackPos.col = colA.int16
colA = 0 colA = 0
when defined(nimpretty): when defined(nimpretty):
tok.offsetB = L.offsetBase + pos tok.offsetB = L.offsetBase + pos
@ -284,10 +284,10 @@ template tokenEnd(tok, pos) {.dirty.} =
template tokenEndIgnore(tok, pos) = template tokenEndIgnore(tok, pos) =
when defined(nimsuggest): when defined(nimsuggest):
let colB = getColNumber(L, pos) let colB = getColNumber(L, pos)
if L.fileIdx == gTrackPos.fileIndex and gTrackPos.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 == gTrackPos.line.int and L.config.ideCmd in {ideSug, ideCon}: L.lineNumber == L.config.m.trackPos.line.int and L.config.ideCmd in {ideSug, ideCon}:
gTrackPos.fileIndex = trackPosInvalidFileIdx L.config.m.trackPos.fileIndex = trackPosInvalidFileIdx
gTrackPos.line = 0'u16 L.config.m.trackPos.line = 0'u16
colA = 0 colA = 0
when defined(nimpretty): when defined(nimpretty):
tok.offsetB = L.offsetBase + pos tok.offsetB = L.offsetBase + pos
@ -298,11 +298,11 @@ template tokenEndPrevious(tok, pos) =
# to the token that came before that, but only if we haven't detected # to the token that came before that, but only if we haven't detected
# the cursor in a string literal or comment: # the cursor in a string literal or comment:
let colB = getColNumber(L, pos) let colB = getColNumber(L, pos)
if L.fileIdx == gTrackPos.fileIndex and gTrackPos.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 == gTrackPos.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.cursor = CursorPosition.BeforeToken
gTrackPos = L.previousToken L.config.m.trackPos = L.previousToken
gTrackPosAttached = 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
@ -1121,9 +1121,9 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
else: else:
tok.tokType = tkParLe tok.tokType = tkParLe
when defined(nimsuggest): when defined(nimsuggest):
if L.fileIdx == gTrackPos.fileIndex and tok.col < gTrackPos.col and if L.fileIdx == L.config.m.trackPos.fileIndex and tok.col < L.config.m.trackPos.col and
tok.line == gTrackPos.line.int and L.config.ideCmd == ideCon: tok.line == L.config.m.trackPos.line.int and L.config.ideCmd == ideCon:
gTrackPos.col = tok.col.int16 L.config.m.trackPos.col = tok.col.int16
of ')': of ')':
tok.tokType = tkParRi tok.tokType = tkParRi
inc(L.bufpos) inc(L.bufpos)
@ -1142,11 +1142,11 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
inc(L.bufpos) inc(L.bufpos)
of '.': of '.':
when defined(nimsuggest): when defined(nimsuggest):
if L.fileIdx == gTrackPos.fileIndex and tok.col+1 == gTrackPos.col and if L.fileIdx == L.config.m.trackPos.fileIndex and tok.col+1 == L.config.m.trackPos.col and
tok.line == gTrackPos.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.cursor = CursorPosition.InToken
gTrackPos.col = tok.col.int16 L.config.m.trackPos.col = tok.col.int16
inc(L.bufpos) inc(L.bufpos)
atTokenEnd() atTokenEnd()
return return

View file

@ -11,7 +11,7 @@
import import
intsets, strutils, options, ast, astalgo, msgs, intsets, strutils, options, ast, astalgo, msgs,
idents, renderer, types, lowerings idents, renderer, types, lowerings, lineinfos
from pragmas import getPragmaVal from pragmas import getPragmaVal
from wordrecg import wLiftLocals from wordrecg import wLiftLocals

264
compiler/lineinfos.nim Normal file
View file

@ -0,0 +1,264 @@
#
#
# The Nim Compiler
# (c) Copyright 2018 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module contains the ``TMsgKind`` enum as well as the
## ``TLineInfo`` object.
import ropes, tables
const
explanationsBaseUrl* = "https://nim-lang.org/docs/manual"
type
TMsgKind* = enum
errUnknown, errInternal, errIllFormedAstX, errCannotOpenFile,
errXExpected,
errGridTableNotImplemented,
errGeneralParseError,
errNewSectionExpected,
errInvalidDirectiveX,
errGenerated,
errUser,
warnCannotOpenFile,
warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit,
warnDeprecated, warnConfigDeprecated,
warnSmallLshouldNotBeUsed, warnUnknownMagic, warnRedefinitionOfLabel,
warnUnknownSubstitutionX, warnLanguageXNotSupported,
warnFieldXNotSupported, warnCommentXIgnored,
warnTypelessParam,
warnUseBase, warnWriteToForeignHeap, warnUnsafeCode,
warnEachIdentIsTuple, warnShadowIdent,
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
warnInconsistentSpacing, warnUser,
hintSuccess, hintSuccessX,
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
hintConditionAlwaysTrue, hintName, hintPattern,
hintExecuting, hintLinking, hintDependency,
hintSource, hintPerformance, hintStackTrace, hintGCStats,
hintUser, hintUserRaw
const
MsgKindToStr*: array[TMsgKind, string] = [
errUnknown: "unknown error",
errInternal: "internal error: $1",
errIllFormedAstX: "illformed AST: $1",
errCannotOpenFile: "cannot open '$1'",
errXExpected: "'$1' expected",
errGridTableNotImplemented: "grid table is not implemented",
errGeneralParseError: "general parse error",
errNewSectionExpected: "new section expected",
errInvalidDirectiveX: "invalid directive: '$1'",
errGenerated: "$1",
errUser: "$1",
warnCannotOpenFile: "cannot open '$1'",
warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored",
warnXIsNeverRead: "'$1' is never read",
warnXmightNotBeenInit: "'$1' might not have been initialized",
warnDeprecated: "$1 is deprecated",
warnConfigDeprecated: "config file '$1' is deprecated",
warnSmallLshouldNotBeUsed: "'l' should not be used as an identifier; may look like '1' (one)",
warnUnknownMagic: "unknown magic '$1' might crash the compiler",
warnRedefinitionOfLabel: "redefinition of label '$1'",
warnUnknownSubstitutionX: "unknown substitution '$1'",
warnLanguageXNotSupported: "language '$1' not supported",
warnFieldXNotSupported: "field '$1' not supported",
warnCommentXIgnored: "comment '$1' ignored",
warnTypelessParam: "'$1' has no type. Typeless parameters are deprecated; only allowed for 'template'",
warnUseBase: "use {.base.} for base methods; baseless methods are deprecated",
warnWriteToForeignHeap: "write to foreign heap",
warnUnsafeCode: "unsafe code: '$1'",
warnEachIdentIsTuple: "each identifier is a tuple",
warnShadowIdent: "shadowed identifier: '$1'",
warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.",
warnProveField: "cannot prove that field '$1' is accessible",
warnProveIndex: "cannot prove index '$1' is valid",
warnGcUnsafe: "not GC-safe: '$1'",
warnGcUnsafe2: "$1",
warnUninit: "'$1' might not have been initialized",
warnGcMem: "'$1' uses GC'ed memory",
warnDestructor: "usage of a type with a destructor in a non destructible context. This will become a compile time error in the future.",
warnLockLevel: "$1",
warnResultShadowed: "Special variable 'result' is shadowed.",
warnInconsistentSpacing: "Number of spaces around '$#' is not consistent",
warnUser: "$1",
hintSuccess: "operation successful",
hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#; $#)",
hintLineTooLong: "line too long",
hintXDeclaredButNotUsed: "'$1' is declared but not used",
hintConvToBaseNotNeeded: "conversion to base object is not needed",
hintConvFromXtoItselfNotNeeded: "conversion from $1 to itself is pointless",
hintExprAlwaysX: "expression evaluates always to '$1'",
hintQuitCalled: "quit() called",
hintProcessing: "$1",
hintCodeBegin: "generated code listing:",
hintCodeEnd: "end of listing",
hintConf: "used config file '$1'",
hintPath: "added path: '$1'",
hintConditionAlwaysTrue: "condition is always true: '$1'",
hintName: "name should be: '$1'",
hintPattern: "$1",
hintExecuting: "$1",
hintLinking: "",
hintDependency: "$1",
hintSource: "$1",
hintPerformance: "$1",
hintStackTrace: "$1",
hintGCStats: "$1",
hintUser: "$1",
hintUserRaw: "$1"]
const
WarningsToStr* = ["CannotOpenFile", "OctalEscape",
"XIsNeverRead", "XmightNotBeenInit",
"Deprecated", "ConfigDeprecated",
"SmallLshouldNotBeUsed", "UnknownMagic",
"RedefinitionOfLabel", "UnknownSubstitutionX",
"LanguageXNotSupported", "FieldXNotSupported",
"CommentXIgnored",
"TypelessParam", "UseBase", "WriteToForeignHeap",
"UnsafeCode", "EachIdentIsTuple", "ShadowIdent",
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
"GcMem", "Destructor", "LockLevel", "ResultShadowed",
"Spacing", "User"]
HintsToStr* = ["Success", "SuccessX", "LineTooLong",
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
"Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency",
"Source", "Performance", "StackTrace", "GCStats",
"User", "UserRaw"]
const
fatalMin* = errUnknown
fatalMax* = errInternal
errMin* = errUnknown
errMax* = errUser
warnMin* = warnCannotOpenFile
warnMax* = pred(hintSuccess)
hintMin* = hintSuccess
hintMax* = high(TMsgKind)
static:
doAssert HintsToStr.len == ord(hintMax) - ord(hintMin) + 1
doAssert WarningsToStr.len == ord(warnMax) - ord(warnMin) + 1
type
TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints
TNoteKinds* = set[TNoteKind]
const
NotesVerbosity*: array[0..3, TNoteKinds] = [
{low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent, warnUninit,
warnProveField, warnProveIndex,
warnGcUnsafe,
hintSuccessX, hintPath, hintConf,
hintProcessing, hintPattern,
hintDependency,
hintExecuting, hintLinking,
hintCodeBegin, hintCodeEnd,
hintSource, hintStackTrace,
hintGCStats},
{low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent, warnUninit,
warnProveField, warnProveIndex,
warnGcUnsafe,
hintPath,
hintDependency,
hintCodeBegin, hintCodeEnd,
hintSource, hintStackTrace,
hintGCStats},
{low(TNoteKind)..high(TNoteKind)} - {hintStackTrace, warnUninit},
{low(TNoteKind)..high(TNoteKind)}]
const
errXMustBeCompileTime* = "'$1' can only be used in compile-time context"
errArgsNeedRunOption* = "arguments can only be given if the '--run' option is selected"
type
TFileInfo* = object
fullPath*: string # This is a canonical full filesystem path
projPath*: string # This is relative to the project's root
shortName*: string # short name of the module
quotedName*: Rope # cached quoted short name for codegen
# purposes
quotedFullName*: Rope # cached quoted full name for codegen
# purposes
lines*: seq[Rope] # the source code of the module
# used for better error messages and
# embedding the original source in the
# generated code
dirtyfile*: string # the file that is actually read into memory
# and parsed; usually "" but is used
# for 'nimsuggest'
hash*: string # the checksum of the file
when defined(nimpretty):
fullContent*: string
FileIndex* = distinct int32
TLineInfo* = object # This is designed to be as small as possible,
# because it is used
# in syntax nodes. We save space here by using
# two int16 and an int32.
# On 64 bit and on 32 bit systems this is
# only 8 bytes.
line*: uint16
col*: int16
fileIndex*: FileIndex
when defined(nimpretty):
offsetA*, offsetB*: int
commentOffsetA*, commentOffsetB*: int
TErrorOutput* = enum
eStdOut
eStdErr
TErrorOutputs* = set[TErrorOutput]
ERecoverableError* = object of ValueError
ESuggestDone* = object of Exception
proc `==`*(a, b: FileIndex): bool {.borrow.}
const
InvalidFileIDX* = FileIndex(-1)
proc unknownLineInfo*(): TLineInfo =
result.line = uint16(0)
result.col = int16(-1)
result.fileIndex = InvalidFileIDX
type
Severity* {.pure.} = enum ## VS Code only supports these three
Hint, Warning, Error
const trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions
# are produced within comments and string literals
type
MsgConfig* = object
trackPos*: TLineInfo
trackPosAttached*: bool ## whether the tracking position was attached to some
## close token.
errorOutputs*: TErrorOutputs
msgContext*: seq[TLineInfo]
lastError*: TLineInfo
filenameToIndexTbl*: Table[string, FileIndex]
fileInfos*: seq[TFileInfo]
systemFileIdx*: FileIndex
proc initMsgConfig*(): MsgConfig =
result.msgContext = @[]
result.lastError = unknownLineInfo()
result.filenameToIndexTbl = initTable[string, FileIndex]()
result.fileInfos = @[]
result.errorOutputs = {eStdOut, eStdErr}

View file

@ -11,7 +11,7 @@
import import
intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread, intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread,
renderer, wordrecg, idgen, nimfix.prettybase, configuration, strutils renderer, wordrecg, idgen, nimfix.prettybase, lineinfos, strutils
proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope) proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope)

View file

@ -12,7 +12,8 @@
const const
genPrefix* = ":tmp" # prefix for generated names genPrefix* = ":tmp" # prefix for generated names
import ast, astalgo, types, idents, magicsys, msgs, options, modulegraphs import ast, astalgo, types, idents, magicsys, msgs, options, modulegraphs,
lineinfos
from trees import getMagic from trees import getMagic
proc newDeref*(n: PNode): PNode {.inline.} = proc newDeref*(n: PNode): PNode {.inline.} =

View file

@ -11,7 +11,7 @@
import import
ast, astalgo, hashes, msgs, platform, nversion, times, idents, rodread, ast, astalgo, hashes, msgs, platform, nversion, times, idents, rodread,
modulegraphs modulegraphs, lineinfos
export createMagic export createMagic

View file

@ -16,7 +16,7 @@ import
cgen, jsgen, json, nversion, cgen, jsgen, json, nversion,
platform, nimconf, importer, passaux, depends, vm, vmdef, types, idgen, platform, nimconf, importer, passaux, depends, vm, vmdef, types, idgen,
docgen2, service, parser, modules, ccgutils, sigmatch, ropes, docgen2, service, parser, modules, ccgutils, sigmatch, ropes,
modulegraphs, tables, rod, configuration modulegraphs, tables, rod, lineinfos
from magicsys import resetSysTypes from magicsys import resetSysTypes

View file

@ -25,7 +25,7 @@
## - Its dependent module stays the same. ## - Its dependent module stays the same.
## ##
import ast, intsets, tables, options, rod, msgs, hashes, idents import ast, intsets, tables, options, rod, lineinfos, hashes, idents
type type
ModuleGraph* = ref object ModuleGraph* = ref object

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
import ast, renderer, strutils, msgs, options, idents, os import ast, renderer, strutils, msgs, options, idents, os, lineinfos
import nimblecmd import nimblecmd

View file

@ -12,7 +12,7 @@
import import
ast, astalgo, magicsys, std / sha1, rodread, msgs, cgendata, sigmatch, options, ast, astalgo, magicsys, std / sha1, rodread, msgs, cgendata, sigmatch, options,
idents, os, lexer, idgen, passes, syntaxes, llstream, modulegraphs, rod, idents, os, lexer, idgen, passes, syntaxes, llstream, modulegraphs, rod,
configuration lineinfos
proc resetSystemArtifacts*(g: ModuleGraph) = proc resetSystemArtifacts*(g: ModuleGraph) =
magicsys.resetSysTypes(g) magicsys.resetSysTypes(g)
@ -118,8 +118,8 @@ proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex;
proc compileSystemModule*(graph: ModuleGraph; cache: IdentCache) = proc compileSystemModule*(graph: ModuleGraph; cache: IdentCache) =
if graph.systemModule == nil: if graph.systemModule == nil:
systemFileIdx = fileInfoIdx(graph.config, graph.config.libpath / "system.nim") graph.config.m.systemFileIdx = fileInfoIdx(graph.config, graph.config.libpath / "system.nim")
discard graph.compileModule(systemFileIdx, cache, {sfSystemModule}) discard graph.compileModule(graph.config.m.systemFileIdx, cache, {sfSystemModule})
proc wantMainModule*(conf: ConfigRef) = proc wantMainModule*(conf: ConfigRef) =
if conf.projectFull.len == 0: if conf.projectFull.len == 0:

View file

@ -9,83 +9,28 @@
import import
options, strutils, os, tables, ropes, platform, terminal, macros, options, strutils, os, tables, ropes, platform, terminal, macros,
configuration lineinfos
#type proc toCChar*(c: char; result: var string) =
# MsgConfig* = ref object of RootObj
type
TFileInfo* = object
fullPath: string # This is a canonical full filesystem path
projPath*: string # This is relative to the project's root
shortName*: string # short name of the module
quotedName*: Rope # cached quoted short name for codegen
# purposes
quotedFullName*: Rope # cached quoted full name for codegen
# purposes
lines*: seq[Rope] # the source code of the module
# used for better error messages and
# embedding the original source in the
# generated code
dirtyfile: string # the file that is actually read into memory
# and parsed; usually 'nil' but is used
# for 'nimsuggest'
hash*: string # the checksum of the file
when defined(nimpretty):
fullContent*: string
FileIndex* = distinct int32
TLineInfo* = object # This is designed to be as small as possible,
# because it is used
# in syntax nodes. We save space here by using
# two int16 and an int32.
# On 64 bit and on 32 bit systems this is
# only 8 bytes.
line*: uint16
col*: int16
fileIndex*: FileIndex
when defined(nimpretty):
offsetA*, offsetB*: int
commentOffsetA*, commentOffsetB*: int
TErrorOutput* = enum
eStdOut
eStdErr
TErrorOutputs* = set[TErrorOutput]
ERecoverableError* = object of ValueError
ESuggestDone* = object of Exception
proc `==`*(a, b: FileIndex): bool {.borrow.}
const
InvalidFileIDX* = FileIndex(-1)
var
filenameToIndexTbl = initTable[string, FileIndex]()
fileInfos*: seq[TFileInfo] = @[]
systemFileIdx*: FileIndex
proc toCChar*(c: char): string =
case c case c
of '\0'..'\x1F', '\x7F'..'\xFF': result = '\\' & toOctal(c) of '\0'..'\x1F', '\x7F'..'\xFF':
of '\'', '\"', '\\', '?': result = '\\' & c result.add '\\'
else: result = $(c) result.add toOctal(c)
of '\'', '\"', '\\', '?':
result.add '\\'
result.add c
else:
result.add c
proc makeCString*(s: string): Rope = proc makeCString*(s: string): Rope =
const const MaxLineLength = 64
MaxLineLength = 64
result = nil result = nil
var res = newStringOfCap(int(s.len.toFloat * 1.1) + 1) var res = newStringOfCap(int(s.len.toFloat * 1.1) + 1)
add(res, "\"") add(res, "\"")
for i in countup(0, len(s) - 1): for i in countup(0, len(s) - 1):
if (i + 1) mod MaxLineLength == 0: if (i + 1) mod MaxLineLength == 0:
add(res, '\"') add(res, "\"\L\"")
add(res, '\L') toCChar(s[i], res)
add(res, '\"')
add(res, toCChar(s[i]))
add(res, '\"') add(res, '\"')
add(result, rope(res)) add(result, rope(res))
@ -110,8 +55,8 @@ proc newFileInfo(fullPath, projPath: string): TFileInfo =
result.fullContent = "" result.fullContent = ""
when defined(nimpretty): when defined(nimpretty):
proc fileSection*(fid: FileIndex; a, b: int): string = proc fileSection*(conf: ConfigRef; fid: FileIndex; a, b: int): string =
substr(fileInfos[fid.int].fullContent, a, b) substr(conf.m.fileInfos[fid.int].fullContent, a, b)
proc fileInfoKnown*(conf: ConfigRef; filename: string): bool = proc fileInfoKnown*(conf: ConfigRef; filename: string): bool =
var var
@ -120,7 +65,7 @@ proc fileInfoKnown*(conf: ConfigRef; filename: string): bool =
canon = canonicalizePath(conf, filename) canon = canonicalizePath(conf, filename)
except: except:
canon = filename canon = filename
result = filenameToIndexTbl.hasKey(canon) result = conf.m.filenameToIndexTbl.hasKey(canon)
proc fileInfoIdx*(conf: ConfigRef; filename: string; isKnownFile: var bool): FileIndex = proc fileInfoIdx*(conf: ConfigRef; filename: string; isKnownFile: var bool): FileIndex =
var var
@ -136,14 +81,14 @@ proc fileInfoIdx*(conf: ConfigRef; filename: string; isKnownFile: var bool): Fil
# This flag indicates that we are working with such a path here # This flag indicates that we are working with such a path here
pseudoPath = true pseudoPath = true
if filenameToIndexTbl.hasKey(canon): if conf.m.filenameToIndexTbl.hasKey(canon):
result = filenameToIndexTbl[canon] result = conf.m.filenameToIndexTbl[canon]
else: else:
isKnownFile = false isKnownFile = false
result = fileInfos.len.FileIndex result = conf.m.fileInfos.len.FileIndex
fileInfos.add(newFileInfo(canon, if pseudoPath: filename conf.m.fileInfos.add(newFileInfo(canon, if pseudoPath: filename
else: shortenDir(conf, canon))) else: shortenDir(conf, canon)))
filenameToIndexTbl[canon] = result conf.m.filenameToIndexTbl[canon] = result
proc fileInfoIdx*(conf: ConfigRef; filename: string): FileIndex = proc fileInfoIdx*(conf: ConfigRef; filename: string): FileIndex =
var dummy: bool var dummy: bool
@ -162,36 +107,19 @@ proc raiseRecoverableError*(msg: string) {.noinline, noreturn.} =
proc sourceLine*(conf: ConfigRef; i: TLineInfo): Rope proc sourceLine*(conf: ConfigRef; i: TLineInfo): Rope
proc unknownLineInfo*(): TLineInfo =
result.line = uint16(0)
result.col = int16(-1)
result.fileIndex = InvalidFileIDX
type
Severity* {.pure.} = enum ## VS Code only supports these three
Hint, Warning, Error
var
msgContext: seq[TLineInfo] = @[]
lastError = unknownLineInfo()
errorOutputs* = {eStdOut, eStdErr}
writelnHook*: proc (output: string) {.closure.}
structuredErrorHook*: proc (config: ConfigRef; info: TLineInfo; msg: string; severity: Severity) {.closure.}
proc concat(strings: openarray[string]): string = proc concat(strings: openarray[string]): string =
var totalLen = 0 var totalLen = 0
for s in strings: totalLen += s.len for s in strings: totalLen += s.len
result = newStringOfCap totalLen result = newStringOfCap totalLen
for s in strings: result.add s for s in strings: result.add s
proc suggestWriteln*(s: string) = proc suggestWriteln*(conf: ConfigRef; s: string) =
if eStdOut in errorOutputs: if eStdOut in conf.m.errorOutputs:
if isNil(writelnHook): if isNil(conf.writelnHook):
writeLine(stdout, s) writeLine(stdout, s)
flushFile(stdout) flushFile(stdout)
else: else:
writelnHook(s) conf.writelnHook(s)
proc msgQuit*(x: int8) = quit x proc msgQuit*(x: int8) = quit x
proc msgQuit*(x: string) = quit x proc msgQuit*(x: string) = quit x
@ -212,47 +140,47 @@ const
HintTitle = "Hint: " HintTitle = "Hint: "
HintColor = fgGreen HintColor = fgGreen
proc getInfoContextLen*(): int = return msgContext.len proc getInfoContextLen*(conf: ConfigRef): int = return conf.m.msgContext.len
proc setInfoContextLen*(L: int) = setLen(msgContext, L) proc setInfoContextLen*(conf: ConfigRef; L: int) = setLen(conf.m.msgContext, L)
proc pushInfoContext*(info: TLineInfo) = proc pushInfoContext*(conf: ConfigRef; info: TLineInfo) =
msgContext.add(info) conf.m.msgContext.add(info)
proc popInfoContext*() = proc popInfoContext*(conf: ConfigRef) =
setLen(msgContext, len(msgContext) - 1) setLen(conf.m.msgContext, len(conf.m.msgContext) - 1)
proc getInfoContext*(index: int): TLineInfo = proc getInfoContext*(conf: ConfigRef; index: int): TLineInfo =
let L = msgContext.len let L = conf.m.msgContext.len
let i = if index < 0: L + index else: index let i = if index < 0: L + index else: index
if i >=% L: result = unknownLineInfo() if i >=% L: result = unknownLineInfo()
else: result = msgContext[i] else: result = conf.m.msgContext[i]
template toFilename*(conf: ConfigRef; fileIdx: FileIndex): string = template toFilename*(conf: ConfigRef; fileIdx: FileIndex): string =
(if fileIdx.int32 < 0: "???" else: fileInfos[fileIdx.int32].projPath) (if fileIdx.int32 < 0: "???" else: conf.m.fileInfos[fileIdx.int32].projPath)
proc toFullPath*(conf: ConfigRef; fileIdx: FileIndex): string = proc toFullPath*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0: result = "???" if fileIdx.int32 < 0: result = "???"
else: result = fileInfos[fileIdx.int32].fullPath else: result = conf.m.fileInfos[fileIdx.int32].fullPath
proc setDirtyFile*(conf: ConfigRef; fileIdx: FileIndex; filename: string) = proc setDirtyFile*(conf: ConfigRef; fileIdx: FileIndex; filename: string) =
assert fileIdx.int32 >= 0 assert fileIdx.int32 >= 0
fileInfos[fileIdx.int32].dirtyFile = filename conf.m.fileInfos[fileIdx.int32].dirtyFile = filename
proc setHash*(conf: ConfigRef; fileIdx: FileIndex; hash: string) = proc setHash*(conf: ConfigRef; fileIdx: FileIndex; hash: string) =
assert fileIdx.int32 >= 0 assert fileIdx.int32 >= 0
shallowCopy(fileInfos[fileIdx.int32].hash, hash) shallowCopy(conf.m.fileInfos[fileIdx.int32].hash, hash)
proc getHash*(conf: ConfigRef; fileIdx: FileIndex): string = proc getHash*(conf: ConfigRef; fileIdx: FileIndex): string =
assert fileIdx.int32 >= 0 assert fileIdx.int32 >= 0
shallowCopy(result, fileInfos[fileIdx.int32].hash) shallowCopy(result, conf.m.fileInfos[fileIdx.int32].hash)
proc toFullPathConsiderDirty*(conf: ConfigRef; fileIdx: FileIndex): string = proc toFullPathConsiderDirty*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0: if fileIdx.int32 < 0:
result = "???" result = "???"
elif not fileInfos[fileIdx.int32].dirtyFile.isNil: elif not conf.m.fileInfos[fileIdx.int32].dirtyFile.isNil:
result = fileInfos[fileIdx.int32].dirtyFile result = conf.m.fileInfos[fileIdx.int32].dirtyFile
else: else:
result = fileInfos[fileIdx.int32].fullPath result = conf.m.fileInfos[fileIdx.int32].fullPath
template toFilename*(conf: ConfigRef; info: TLineInfo): string = template toFilename*(conf: ConfigRef; info: TLineInfo): string =
toFilename(conf, info.fileIndex) toFilename(conf, info.fileIndex)
@ -264,9 +192,9 @@ proc toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
if info.fileIndex.int32 < 0: if info.fileIndex.int32 < 0:
result = "???" result = "???"
elif optListFullPaths in conf.globalOptions: elif optListFullPaths in conf.globalOptions:
result = fileInfos[info.fileIndex.int32].fullPath result = conf.m.fileInfos[info.fileIndex.int32].fullPath
else: else:
result = fileInfos[info.fileIndex.int32].projPath result = conf.m.fileInfos[info.fileIndex.int32].projPath
proc toLinenumber*(info: TLineInfo): int {.inline.} = proc toLinenumber*(info: TLineInfo): int {.inline.} =
result = int info.line result = int info.line
@ -288,12 +216,6 @@ proc `??`* (conf: ConfigRef; info: TLineInfo, filename: string): bool =
# only for debugging purposes # only for debugging purposes
result = filename in toFilename(conf, info) result = filename in toFilename(conf, info)
const trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions
# are produced within comments and string literals
var gTrackPos*: TLineInfo
var gTrackPosAttached*: bool ## whether the tracking position was attached to some
## close token.
type type
MsgFlag* = enum ## flags altering msgWriteln behavior MsgFlag* = enum ## flags altering msgWriteln behavior
msgStdout, ## force writing to stdout, even stderr is default msgStdout, ## force writing to stdout, even stderr is default
@ -310,14 +232,14 @@ proc msgWriteln*(conf: ConfigRef; s: string, flags: MsgFlags = {}) =
## support. ## support.
#if conf.cmd == cmdIdeTools and optCDebug notin gGlobalOptions: return #if conf.cmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
if not isNil(writelnHook) and msgSkipHook notin flags: if not isNil(conf.writelnHook) and msgSkipHook notin flags:
writelnHook(s) conf.writelnHook(s)
elif optStdout in conf.globalOptions or msgStdout in flags: elif optStdout in conf.globalOptions or msgStdout in flags:
if eStdOut in errorOutputs: if eStdOut in conf.m.errorOutputs:
writeLine(stdout, s) writeLine(stdout, s)
flushFile(stdout) flushFile(stdout)
else: else:
if eStdErr in errorOutputs: if eStdErr in conf.m.errorOutputs:
writeLine(stderr, s) writeLine(stderr, s)
# On Windows stderr is fully-buffered when piped, regardless of C std. # On Windows stderr is fully-buffered when piped, regardless of C std.
when defined(windows): when defined(windows):
@ -348,17 +270,17 @@ macro callStyledWriteLineStderr(args: varargs[typed]): untyped =
result.add(arg) result.add(arg)
template callWritelnHook(args: varargs[string, `$`]) = template callWritelnHook(args: varargs[string, `$`]) =
writelnHook concat(args) conf.writelnHook concat(args)
template styledMsgWriteln*(args: varargs[typed]) = template styledMsgWriteln*(args: varargs[typed]) =
if not isNil(writelnHook): if not isNil(conf.writelnHook):
callIgnoringStyle(callWritelnHook, nil, args) callIgnoringStyle(callWritelnHook, nil, args)
elif optStdout in conf.globalOptions: elif optStdout in conf.globalOptions:
if eStdOut in errorOutputs: if eStdOut in conf.m.errorOutputs:
callIgnoringStyle(writeLine, stdout, args) callIgnoringStyle(writeLine, stdout, args)
flushFile(stdout) flushFile(stdout)
else: else:
if eStdErr in errorOutputs: if eStdErr in conf.m.errorOutputs:
if optUseColors in conf.globalOptions: if optUseColors in conf.globalOptions:
callStyledWriteLineStderr(args) callStyledWriteLineStderr(args)
else: else:
@ -389,7 +311,7 @@ proc log*(s: string) {.procvar.} =
proc quit(conf: ConfigRef; msg: TMsgKind) = proc quit(conf: ConfigRef; msg: TMsgKind) =
if defined(debug) or msg == errInternal or hintStackTrace in conf.notes: if defined(debug) or msg == errInternal or hintStackTrace in conf.notes:
if stackTraceAvailable() and isNil(writelnHook): if stackTraceAvailable() and isNil(conf.writelnHook):
writeStackTrace() writeStackTrace()
else: else:
styledMsgWriteln(fgRed, "No stack traceback available\n" & styledMsgWriteln(fgRed, "No stack traceback available\n" &
@ -420,19 +342,19 @@ proc exactEquals*(a, b: TLineInfo): bool =
proc writeContext(conf: ConfigRef; lastinfo: TLineInfo) = proc writeContext(conf: ConfigRef; lastinfo: TLineInfo) =
const instantiationFrom = "template/generic instantiation from here" const instantiationFrom = "template/generic instantiation from here"
var info = lastinfo var info = lastinfo
for i in countup(0, len(msgContext) - 1): for i in 0 ..< len(conf.m.msgContext):
if msgContext[i] != lastinfo and msgContext[i] != info: if conf.m.msgContext[i] != lastinfo and conf.m.msgContext[i] != info:
if structuredErrorHook != nil: if conf.structuredErrorHook != nil:
structuredErrorHook(conf, msgContext[i], instantiationFrom, conf.structuredErrorHook(conf, conf.m.msgContext[i], instantiationFrom,
Severity.Error) Severity.Error)
else: else:
styledMsgWriteln(styleBright, styledMsgWriteln(styleBright,
PosFormat % [toMsgFilename(conf, msgContext[i]), PosFormat % [toMsgFilename(conf, conf.m.msgContext[i]),
coordToStr(msgContext[i].line.int), coordToStr(conf.m.msgContext[i].line.int),
coordToStr(msgContext[i].col+1)], coordToStr(conf.m.msgContext[i].col+1)],
resetStyle, resetStyle,
instantiationFrom) instantiationFrom)
info = msgContext[i] info = conf.m.msgContext[i]
proc ignoreMsgBecauseOfIdeTools(conf: ConfigRef; msg: TMsgKind): bool = proc ignoreMsgBecauseOfIdeTools(conf: ConfigRef; msg: TMsgKind): bool =
msg >= errGenerated and conf.cmd == cmdIdeTools and optIdeDebug notin conf.globalOptions msg >= errGenerated and conf.cmd == cmdIdeTools and optIdeDebug notin conf.globalOptions
@ -468,8 +390,9 @@ proc rawMessage*(conf: ConfigRef; msg: TMsgKind, args: openArray[string]) =
inc(conf.hintCounter) inc(conf.hintCounter)
let s = msgKindToString(msg) % args let s = msgKindToString(msg) % args
if structuredErrorHook != nil: if conf.structuredErrorHook != nil:
structuredErrorHook(conf, unknownLineInfo(), s & (if kind != nil: KindFormat % kind else: ""), sev) conf.structuredErrorHook(conf, unknownLineInfo(),
s & (if kind != nil: KindFormat % kind else: ""), sev)
if not ignoreMsgBecauseOfIdeTools(conf, msg): if not ignoreMsgBecauseOfIdeTools(conf, msg):
if kind != nil: if kind != nil:
@ -518,7 +441,7 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
# we try to filter error messages so that not two error message # we try to filter error messages so that not two error message
# in the same file and line are produced: # in the same file and line are produced:
#ignoreMsg = lastError == info and eh != doAbort #ignoreMsg = lastError == info and eh != doAbort
lastError = info conf.m.lastError = info
of warnMin..warnMax: of warnMin..warnMax:
sev = Severity.Warning sev = Severity.Warning
ignoreMsg = optWarns notin conf.options or msg notin conf.notes ignoreMsg = optWarns notin conf.options or msg notin conf.notes
@ -542,8 +465,8 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
let s = getMessageStr(msg, arg) let s = getMessageStr(msg, arg)
if not ignoreMsg: if not ignoreMsg:
if structuredErrorHook != nil: if conf.structuredErrorHook != nil:
structuredErrorHook(conf, info, s & (if kind != nil: KindFormat % kind else: ""), sev) conf.structuredErrorHook(conf, info, s & (if kind != nil: KindFormat % kind else: ""), sev)
if not ignoreMsgBecauseOfIdeTools(conf, msg): if not ignoreMsgBecauseOfIdeTools(conf, msg):
if kind != nil: if kind != nil:
styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s, styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s,
@ -557,7 +480,7 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
proc fatal*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") = proc fatal*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
# this fixes bug #7080 so that it is at least obvious 'fatal' # this fixes bug #7080 so that it is at least obvious 'fatal'
# was executed. # was executed.
errorOutputs = {eStdOut, eStdErr} conf.m.errorOutputs = {eStdOut, eStdErr}
liMessage(conf, info, msg, arg, doAbort) liMessage(conf, info, msg, arg, doAbort)
proc globalError*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") = proc globalError*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
@ -579,12 +502,12 @@ proc message*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(conf, info, msg, arg, doNothing) liMessage(conf, info, msg, arg, doNothing)
proc internalError*(conf: ConfigRef; info: TLineInfo, errMsg: string) = proc internalError*(conf: ConfigRef; info: TLineInfo, errMsg: string) =
if conf.cmd == cmdIdeTools and structuredErrorHook.isNil: return if conf.cmd == cmdIdeTools and conf.structuredErrorHook.isNil: return
writeContext(conf, info) writeContext(conf, info)
liMessage(conf, info, errInternal, errMsg, doAbort) liMessage(conf, info, errInternal, errMsg, doAbort)
proc internalError*(conf: ConfigRef; errMsg: string) = proc internalError*(conf: ConfigRef; errMsg: string) =
if conf.cmd == cmdIdeTools and structuredErrorHook.isNil: return if conf.cmd == cmdIdeTools and conf.structuredErrorHook.isNil: return
writeContext(conf, unknownLineInfo()) writeContext(conf, unknownLineInfo())
rawMessage(conf, errInternal, errMsg) rawMessage(conf, errInternal, errMsg)
@ -596,36 +519,36 @@ template internalAssert*(conf: ConfigRef, e: bool) =
if not e: internalError(conf, $instantiationInfo()) if not e: internalError(conf, $instantiationInfo())
proc addSourceLine*(conf: ConfigRef; fileIdx: FileIndex, line: string) = proc addSourceLine*(conf: ConfigRef; fileIdx: FileIndex, line: string) =
fileInfos[fileIdx.int32].lines.add line.rope conf.m.fileInfos[fileIdx.int32].lines.add line.rope
proc sourceLine*(conf: ConfigRef; i: TLineInfo): Rope = proc sourceLine*(conf: ConfigRef; i: TLineInfo): Rope =
if i.fileIndex.int32 < 0: return nil if i.fileIndex.int32 < 0: return nil
if not optPreserveOrigSource(conf) and fileInfos[i.fileIndex.int32].lines.len == 0: if not optPreserveOrigSource(conf) and conf.m.fileInfos[i.fileIndex.int32].lines.len == 0:
try: try:
for line in lines(toFullPath(conf, i)): for line in lines(toFullPath(conf, i)):
addSourceLine conf, i.fileIndex, line.string addSourceLine conf, i.fileIndex, line.string
except IOError: except IOError:
discard discard
assert i.fileIndex.int32 < fileInfos.len assert i.fileIndex.int32 < conf.m.fileInfos.len
# can happen if the error points to EOF: # can happen if the error points to EOF:
if i.line.int > fileInfos[i.fileIndex.int32].lines.len: return nil if i.line.int > conf.m.fileInfos[i.fileIndex.int32].lines.len: return nil
result = fileInfos[i.fileIndex.int32].lines[i.line.int-1] result = conf.m.fileInfos[i.fileIndex.int32].lines[i.line.int-1]
proc quotedFilename*(conf: ConfigRef; i: TLineInfo): Rope = proc quotedFilename*(conf: ConfigRef; i: TLineInfo): Rope =
assert i.fileIndex.int32 >= 0 assert i.fileIndex.int32 >= 0
if optExcessiveStackTrace in conf.globalOptions: if optExcessiveStackTrace in conf.globalOptions:
result = fileInfos[i.fileIndex.int32].quotedFullName result = conf.m.fileInfos[i.fileIndex.int32].quotedFullName
else: else:
result = fileInfos[i.fileIndex.int32].quotedName result = conf.m.fileInfos[i.fileIndex.int32].quotedName
proc listWarnings*(conf: ConfigRef) = proc listWarnings*(conf: ConfigRef) =
msgWriteln(conf, "Warnings:") msgWriteln(conf, "Warnings:")
for warn in warnMin..warnMax: for warn in warnMin..warnMax:
msgWriteln(conf, " [$1] $2" % [ msgWriteln(conf, " [$1] $2" % [
if warn in conf.notes: "x" else: " ", if warn in conf.notes: "x" else: " ",
configuration.WarningsToStr[ord(warn) - ord(warnMin)] lineinfos.WarningsToStr[ord(warn) - ord(warnMin)]
]) ])
proc listHints*(conf: ConfigRef) = proc listHints*(conf: ConfigRef) =
@ -633,5 +556,5 @@ proc listHints*(conf: ConfigRef) =
for hint in hintMin..hintMax: for hint in hintMin..hintMax:
msgWriteln(conf, " [$1] $2" % [ msgWriteln(conf, " [$1] $2" % [
if hint in conf.notes: "x" else: " ", if hint in conf.notes: "x" else: " ",
configuration.HintsToStr[ord(hint) - ord(hintMin)] lineinfos.HintsToStr[ord(hint) - ord(hintMin)]
]) ])

View file

@ -21,7 +21,7 @@ when defined(i386) and defined(windows) and defined(vcc):
import import
commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes, commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
extccomp, strutils, os, osproc, platform, main, parseopt, service, extccomp, strutils, os, osproc, platform, main, parseopt, service,
nodejs, scriptconfig, idents, modulegraphs, configuration nodejs, scriptconfig, idents, modulegraphs, lineinfos
when hasTinyCBackend: when hasTinyCBackend:
import tccgen import tccgen

View file

@ -10,7 +10,7 @@
## Implements some helper procs for Nimble (Nim's package manager) support. ## Implements some helper procs for Nimble (Nim's package manager) support.
import parseutils, strutils, strtabs, os, options, msgs, sequtils, import parseutils, strutils, strtabs, os, options, msgs, sequtils,
configuration lineinfos
proc addPath*(conf: ConfigRef; path: string, info: TLineInfo) = proc addPath*(conf: ConfigRef; path: string, info: TLineInfo) =
if not conf.searchPaths.contains(path): if not conf.searchPaths.contains(path):

View file

@ -11,7 +11,7 @@
import import
llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer, llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer,
options, idents, wordrecg, strtabs, configuration options, idents, wordrecg, strtabs, lineinfos
# ---------------- 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

View file

@ -14,7 +14,7 @@ import
strutils, os, intsets, strtabs strutils, os, intsets, strtabs
import ".." / [options, ast, astalgo, msgs, semdata, ropes, idents, import ".." / [options, ast, astalgo, msgs, semdata, ropes, idents,
configuration] lineinfos]
import prettybase import prettybase
type type

View file

@ -8,7 +8,7 @@
# #
import strutils, lexbase, streams import strutils, lexbase, streams
import ".." / [ast, msgs, idents, options] import ".." / [ast, msgs, lineinfos, idents, options]
from os import splitFile from os import splitFile
type type

View file

@ -10,7 +10,7 @@
# this unit handles Nim sets; it implements symbolic sets # this unit handles Nim sets; it implements symbolic sets
import import
ast, astalgo, trees, nversion, msgs, platform, bitsets, types, renderer, ast, astalgo, trees, nversion, lineinfos, platform, bitsets, types, renderer,
options options
proc inSet*(s: PNode, elem: PNode): bool = proc inSet*(s: PNode, elem: PNode): bool =

View file

@ -15,6 +15,6 @@ const
VersionAsString* = system.NimVersion VersionAsString* = system.NimVersion
RodFileVersion* = "1223" # modify this if the rod-format changes! RodFileVersion* = "1223" # modify this if the rod-format changes!
NimCompilerApiVersion* = 1 ## Check for the existance of this before accessing it NimCompilerApiVersion* = 2 ## Check for the existance of this before accessing it
## as older versions of the compiler API do not ## as older versions of the compiler API do not
## declare this. ## declare this.

View file

@ -8,7 +8,8 @@
# #
import import
os, strutils, strtabs, osproc, sets, configuration, platform os, strutils, strtabs, osproc, sets, lineinfos, platform,
prefixmatches
from terminal import isatty from terminal import isatty
@ -135,11 +136,33 @@ type
flags*: set[CFileFlag] flags*: set[CFileFlag]
CfileList* = seq[Cfile] CfileList* = seq[Cfile]
Suggest* = ref object
section*: IdeCmd
qualifiedPath*: seq[string]
name*: ptr string # not used beyond sorting purposes; name is also
# part of 'qualifiedPath'
filePath*: string
line*: int # Starts at 1
column*: int # Starts at 0
doc*: string # Not escaped (yet)
forth*: string # type
quality*: range[0..100] # matching quality
isGlobal*: bool # is a global variable
contextFits*: bool # type/non-type context matches
prefix*: PrefixMatch
symkind*: byte
scope*, localUsages*, globalUsages*: int # more usages is better
tokenLen*: int
version*: int
Suggestions* = seq[Suggest]
ConfigRef* = ref object ## eventually all global configuration should be moved here ConfigRef* = ref object ## eventually all global configuration should be moved here
target*: Target target*: Target
linesCompiled*: int # all lines that have been compiled linesCompiled*: int # all lines that have been compiled
options*: TOptions options*: TOptions
globalOptions*: TGlobalOptions globalOptions*: TGlobalOptions
m*: MsgConfig
evalTemplateCounter*: int
exitcode*: int8 exitcode*: int8
cmd*: TCommands # the command cmd*: TCommands # the command
selectedGC*: TGCMode # the selected GC selectedGC*: TGCMode # the selected GC
@ -202,6 +225,13 @@ type
compileOptions*: string compileOptions*: string
ccompilerpath*: string ccompilerpath*: string
toCompile*: CfileList toCompile*: CfileList
suggestionResultHook*: proc (result: Suggest) {.closure.}
suggestVersion*: int
suggestMaxResults*: int
lastLineInfo*: TLineInfo
writelnHook*: proc (output: string) {.closure.}
structuredErrorHook*: proc (config: ConfigRef; info: TLineInfo; msg: string;
severity: Severity) {.closure.}
const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, parallel} const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, parallel}
@ -229,6 +259,7 @@ proc newConfigRef*(): ConfigRef =
verbosity: 1, verbosity: 1,
options: DefaultOptions, options: DefaultOptions,
globalOptions: DefaultGlobalOptions, globalOptions: DefaultGlobalOptions,
m: initMsgConfig(),
evalExpr: "", evalExpr: "",
cppDefines: initSet[string](), cppDefines: initSet[string](),
headerFile: "", features: {}, foreignPackageNotes: {hintProcessing, warnUnknownMagic, headerFile: "", features: {}, foreignPackageNotes: {hintProcessing, warnUnknownMagic,
@ -264,7 +295,8 @@ proc newConfigRef*(): ConfigRef =
compileOptions: "", compileOptions: "",
ccompilerpath: "", ccompilerpath: "",
toCompile: @[], toCompile: @[],
arguments: "" arguments: "",
suggestMaxResults: 10_000
) )
setTargetFromSystem(result.target) setTargetFromSystem(result.target)
# enable colors by default on terminals # enable colors by default on terminals

View file

@ -27,7 +27,7 @@ when isMainModule:
outp.close outp.close
import import
llstream, lexer, idents, strutils, ast, astalgo, msgs, options, configuration llstream, lexer, idents, strutils, ast, astalgo, msgs, options, lineinfos
type type
TParser* = object # A TParser object represents a file that TParser* = object # A TParser object represents a file that

View file

@ -10,7 +10,7 @@
## implements some little helper passes ## implements some little helper passes
import import
strutils, ast, astalgo, passes, idents, msgs, options, idgen, configuration strutils, ast, astalgo, passes, idents, msgs, options, idgen, lineinfos
from modulegraphs import ModuleGraph from modulegraphs import ModuleGraph

View file

@ -14,7 +14,7 @@ import
strutils, options, ast, astalgo, llstream, msgs, platform, os, strutils, options, ast, astalgo, llstream, msgs, platform, os,
condsyms, idents, renderer, types, extccomp, math, magicsys, nversion, condsyms, idents, renderer, types, extccomp, math, magicsys, nversion,
nimsets, syntaxes, times, rodread, idgen, modulegraphs, reorder, rod, nimsets, syntaxes, times, rodread, idgen, modulegraphs, reorder, rod,
configuration lineinfos
type type

View file

@ -12,7 +12,7 @@
import import
os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer, os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer,
wordrecg, ropes, options, strutils, extccomp, math, magicsys, trees, wordrecg, ropes, options, strutils, extccomp, math, magicsys, trees,
rodread, types, lookups, configuration rodread, types, lookups, lineinfos
const const
FirstCallConv* = wNimcall FirstCallConv* = wNimcall
@ -549,7 +549,7 @@ proc pragmaLine(c: PContext, n: PNode) =
localError(c.config, n.info, "tuple expected") localError(c.config, n.info, "tuple expected")
else: else:
# sensible default: # sensible default:
n.info = getInfoContext(-1) n.info = getInfoContext(c.config, -1)
proc processPragma(c: PContext, n: PNode, i: int) = proc processPragma(c: PContext, n: PNode, i: int) =
let it = n[i] let it = n[i]
@ -1047,13 +1047,13 @@ proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
for it in c.optionStack: for it in c.optionStack:
let o = it.otherPragmas let o = it.otherPragmas
if not o.isNil: if not o.isNil:
pushInfoContext(n.info) pushInfoContext(c.config, n.info)
var i = 0 var i = 0
while i < o.len(): while i < o.len():
if singlePragma(c, sym, o, i, validPragmas): if singlePragma(c, sym, o, i, validPragmas):
internalError(c.config, n.info, "implicitPragmas") internalError(c.config, n.info, "implicitPragmas")
inc i inc i
popInfoContext() popInfoContext(c.config)
if lfExportLib in sym.loc.flags and sfExportc notin sym.flags: if lfExportLib in sym.loc.flags and sfExportc notin sym.flags:
localError(c.config, n.info, ".dynlib requires .exportc") localError(c.config, n.info, ".dynlib requires .exportc")

View file

@ -24,7 +24,7 @@ proc prefixMatch*(p, s: string): PrefixMatch =
# check for prefix/contains: # check for prefix/contains:
while i < L: while i < L:
if s[i] == '_': inc i if s[i] == '_': inc i
if eq(s[i], p[0]): if i < L and eq(s[i], p[0]):
var ii = i+1 var ii = i+1
var jj = 1 var jj = 1
while ii < L and jj < p.len: while ii < L and jj < p.len:
@ -43,10 +43,10 @@ proc prefixMatch*(p, s: string): PrefixMatch =
i = 1 i = 1
var j = 1 var j = 1
while i < s.len: while i < s.len:
if s[i] == '_' and i < s.len-1: if i < s.len-1 and s[i] == '_':
if j < p.len and eq(p[j], s[i+1]): inc j if j < p.len and eq(p[j], s[i+1]): inc j
else: return PrefixMatch.None else: return PrefixMatch.None
if s[i] in {'A'..'Z'} and s[i-1] notin {'A'..'Z'}: if i < s.len and s[i] in {'A'..'Z'} and s[i-1] notin {'A'..'Z'}:
if j < p.len and eq(p[j], s[i]): inc j if j < p.len and eq(p[j], s[i]): inc j
else: return PrefixMatch.None else: return PrefixMatch.None
inc i inc i

View file

@ -10,7 +10,7 @@
# This module implements the renderer of the standard Nim representation. # This module implements the renderer of the standard Nim representation.
import import
lexer, options, idents, strutils, ast, msgs, configuration lexer, options, idents, strutils, ast, msgs, lineinfos
type type
TRenderFlag* = enum TRenderFlag* = enum

View file

@ -2,7 +2,7 @@
import import
intsets, ast, idents, algorithm, renderer, parser, ospaths, strutils, intsets, ast, idents, algorithm, renderer, parser, ospaths, strutils,
sequtils, msgs, modulegraphs, syntaxes, options, modulepaths, tables, sequtils, msgs, modulegraphs, syntaxes, options, modulepaths, tables,
configuration lineinfos
type type
DepN = ref object DepN = ref object

View file

@ -9,7 +9,7 @@
## This module implements the canonalization for the various caching mechanisms. ## This module implements the canonalization for the various caching mechanisms.
import ast, idgen, msgs import ast, idgen, lineinfos, msgs
when not defined(nimSymbolfiles): when not defined(nimSymbolfiles):
template setupModuleCache* = discard template setupModuleCache* = discard

View file

@ -91,7 +91,7 @@
import import
os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms, os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms,
ropes, idents, std / sha1, idgen, types, rodutils, memfiles, tables, ropes, idents, std / sha1, idgen, types, rodutils, memfiles, tables,
configuration lineinfos
type type
TReasonForRecompile* = enum ## all the reasons that can trigger recompilation TReasonForRecompile* = enum ## all the reasons that can trigger recompilation
@ -899,7 +899,7 @@ proc checkDep(fileIdx: FileIndex; cache: IdentCache; conf: ConfigRef): TReasonFo
# NOTE: we need to process the entire module graph so that no ID will # NOTE: we need to process the entire module graph so that no ID will
# be used twice! However, compilation speed does not suffer much from # be used twice! However, compilation speed does not suffer much from
# this, since results are cached. # this, since results are cached.
var res = checkDep(systemFileIdx, cache, conf) var res = checkDep(conf.m.systemFileIdx, cache, conf)
if res != rrNone: result = rrModDeps if res != rrNone: result = rrModDeps
for i in countup(0, high(r.modDeps)): for i in countup(0, high(r.modDeps)):
res = checkDep(r.modDeps[i], cache, conf) res = checkDep(r.modDeps[i], cache, conf)

View file

@ -14,7 +14,7 @@
import import
intsets, os, options, strutils, nversion, ast, astalgo, msgs, platform, intsets, os, options, strutils, nversion, ast, astalgo, msgs, platform,
condsyms, ropes, idents, std / sha1, rodread, passes, idgen, condsyms, ropes, idents, std / sha1, rodread, passes, idgen,
rodutils, modulepaths rodutils, modulepaths, lineinfos
from modulegraphs import ModuleGraph from modulegraphs import ModuleGraph

View file

@ -56,7 +56,7 @@
# To cache them they are inserted in a `cache` array. # To cache them they are inserted in a `cache` array.
import import
platform, hashes hashes
type type
FormatStr* = string # later we may change it to CString for better FormatStr* = string # later we may change it to CString for better
@ -70,8 +70,6 @@ type
length*: int length*: int
data*: string # != nil if a leaf data*: string # != nil if a leaf
RopeSeq* = seq[Rope]
proc len*(a: Rope): int = proc len*(a: Rope): int =
## the rope's length ## the rope's length
if a == nil: result = 0 if a == nil: result = 0
@ -93,7 +91,7 @@ proc freezeMutableRope*(r: Rope) {.inline.} =
r.length = r.data.len r.length = r.data.len
var var
cache: array[0..2048*2 - 1, Rope] cache: array[0..2048*2 - 1, Rope] # XXX Global here!
proc resetRopeCache* = proc resetRopeCache* =
for i in low(cache)..high(cache): for i in low(cache)..high(cache):

View file

@ -13,7 +13,7 @@
import import
ast, modules, idents, passes, passaux, condsyms, ast, modules, idents, passes, passaux, condsyms,
options, nimconf, sem, semdata, llstream, vm, vmdef, commands, msgs, options, nimconf, sem, semdata, llstream, vm, vmdef, commands, msgs,
os, times, osproc, wordrecg, strtabs, modulegraphs, configuration os, times, osproc, wordrecg, strtabs, modulegraphs, lineinfos
# we support 'cmpIgnoreStyle' natively for efficiency: # we support 'cmpIgnoreStyle' natively for efficiency:
from strutils import cmpIgnoreStyle, contains from strutils import cmpIgnoreStyle, contains

View file

@ -16,7 +16,7 @@ import
procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch, procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch,
intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting, intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
evaltempl, patterns, parampatterns, sempass2, nimfix.pretty, semmacrosanity, evaltempl, patterns, parampatterns, sempass2, nimfix.pretty, semmacrosanity,
semparallel, lowerings, pluginsupport, plugins.active, rod, configuration semparallel, lowerings, pluginsupport, plugins.active, rod, lineinfos
from modulegraphs import ModuleGraph from modulegraphs import ModuleGraph
@ -52,10 +52,10 @@ proc isArrayConstr(n: PNode): bool {.inline.} =
result = n.kind == nkBracket and result = n.kind == nkBracket and
n.typ.skipTypes(abstractInst).kind == tyArray n.typ.skipTypes(abstractInst).kind == tyArray
template semIdeForTemplateOrGenericCheck(n, requiresCheck) = template semIdeForTemplateOrGenericCheck(conf, n, requiresCheck) =
# we check quickly if the node is where the cursor is # we check quickly if the node is where the cursor is
when defined(nimsuggest): when defined(nimsuggest):
if n.info.fileIndex == gTrackPos.fileIndex and n.info.line == gTrackPos.line: if n.info.fileIndex == conf.m.trackPos.fileIndex and n.info.line == conf.m.trackPos.line:
requiresCheck = true requiresCheck = true
template semIdeForTemplateOrGeneric(c: PContext; n: PNode; template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
@ -307,9 +307,9 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
let oldErrorCount = c.config.errorCounter let oldErrorCount = c.config.errorCounter
let oldErrorMax = c.config.errorMax let oldErrorMax = c.config.errorMax
let oldErrorOutputs = errorOutputs let oldErrorOutputs = c.config.m.errorOutputs
errorOutputs = {} c.config.m.errorOutputs = {}
c.config.errorMax = high(int) c.config.errorMax = high(int)
try: try:
@ -324,7 +324,7 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
c.config.errorCounter = oldErrorCount c.config.errorCounter = oldErrorCount
c.config.errorMax = oldErrorMax c.config.errorMax = oldErrorMax
errorOutputs = oldErrorOutputs c.config.m.errorOutputs = oldErrorOutputs
const const
errConstExprExpected = "constant expression expected" errConstExprExpected = "constant expression expected"
@ -340,9 +340,9 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
result = evalConstExpr(c.module, c.cache, c.graph, e) result = evalConstExpr(c.module, c.cache, c.graph, e)
if result == nil or result.kind == nkEmpty: if result == nil or result.kind == nkEmpty:
if e.info != n.info: if e.info != n.info:
pushInfoContext(n.info) pushInfoContext(c.config, n.info)
localError(c.config, e.info, errConstExprExpected) localError(c.config, e.info, errConstExprExpected)
popInfoContext() popInfoContext(c.config)
else: else:
localError(c.config, e.info, errConstExprExpected) localError(c.config, e.info, errConstExprExpected)
# error correction: # error correction:
@ -380,8 +380,8 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
## coherence, making sure that variables declared with 'let' aren't ## coherence, making sure that variables declared with 'let' aren't
## reassigned, and binding the unbound identifiers that the macro output ## reassigned, and binding the unbound identifiers that the macro output
## contains. ## contains.
inc(evalTemplateCounter) inc(c.config.evalTemplateCounter)
if evalTemplateCounter > evalTemplateLimit: if c.config.evalTemplateCounter > evalTemplateLimit:
globalError(c.config, s.info, "template instantiation too nested") globalError(c.config, s.info, "template instantiation too nested")
c.friendModules.add(s.owner.getModule) c.friendModules.add(s.owner.getModule)
@ -420,8 +420,8 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
result = semExpr(c, result, flags) result = semExpr(c, result, flags)
result = fitNode(c, retType, result, result.info) result = fitNode(c, retType, result, result.info)
#GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0])) #globalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
dec(evalTemplateCounter) dec(c.config.evalTemplateCounter)
discard c.friendModules.pop() discard c.friendModules.pop()
const const
@ -429,7 +429,7 @@ const
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
flags: TExprFlags = {}): PNode = flags: TExprFlags = {}): PNode =
pushInfoContext(nOrig.info) pushInfoContext(c.config, nOrig.info)
markUsed(c.config, n.info, sym, c.graph.usageSym) markUsed(c.config, n.info, sym, c.graph.usageSym)
styleCheckUse(n.info, sym) styleCheckUse(n.info, sym)
@ -449,7 +449,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
if efNoSemCheck notin flags: if efNoSemCheck notin flags:
result = semAfterMacroCall(c, n, result, sym, flags) result = semAfterMacroCall(c, n, result, sym, flags)
result = wrapInComesFrom(nOrig.info, sym, result) result = wrapInComesFrom(nOrig.info, sym, result)
popInfoContext() popInfoContext(c.config)
proc forceBool(c: PContext, n: PNode): PNode = proc forceBool(c: PContext, n: PNode): PNode =
result = fitNode(c, getSysType(c.graph, n.info, tyBool), n, n.info) result = fitNode(c, getSysType(c.graph, n.info, tyBool), n, n.info)
@ -582,14 +582,14 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
if c.config.errorMax <= 1: if c.config.errorMax <= 1:
result = semStmtAndGenerateGenerics(c, n) result = semStmtAndGenerateGenerics(c, n)
else: else:
let oldContextLen = msgs.getInfoContextLen() let oldContextLen = msgs.getInfoContextLen(c.config)
let oldInGenericInst = c.inGenericInst let oldInGenericInst = c.inGenericInst
try: try:
result = semStmtAndGenerateGenerics(c, n) result = semStmtAndGenerateGenerics(c, n)
except ERecoverableError, ESuggestDone: except ERecoverableError, ESuggestDone:
recoverContext(c) recoverContext(c)
c.inGenericInst = oldInGenericInst c.inGenericInst = oldInGenericInst
msgs.setInfoContextLen(oldContextLen) msgs.setInfoContextLen(c.config, oldContextLen)
if getCurrentException() of ESuggestDone: if getCurrentException() of ESuggestDone:
c.suggestionsMade = true c.suggestionsMade = true
result = nil result = nil

View file

@ -213,7 +213,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
# Gives a detailed error message; this is separated from semOverloadedCall, # Gives a detailed error message; this is separated from semOverloadedCall,
# as semOverlodedCall is already pretty slow (and we need this information # as semOverlodedCall is already pretty slow (and we need this information
# only in case of an error). # only in case of an error).
if errorOutputs == {}: if c.config.m.errorOutputs == {}:
# fail fast: # fail fast:
globalError(c.config, n.info, "type mismatch") globalError(c.config, n.info, "type mismatch")
if errors.len == 0: if errors.len == 0:
@ -332,7 +332,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
internalAssert c.config, result.state == csMatch internalAssert c.config, result.state == csMatch
#writeMatches(result) #writeMatches(result)
#writeMatches(alt) #writeMatches(alt)
if errorOutputs == {}: if c.config.m.errorOutputs == {}:
# quick error message for performance of 'compiles' built-in: # quick error message for performance of 'compiles' built-in:
globalError(c.config, n.info, errGenerated, "ambiguous call") globalError(c.config, n.info, errGenerated, "ambiguous call")
elif c.config.errorCounter == 0: elif c.config.errorCounter == 0:

View file

@ -14,7 +14,7 @@ import
wordrecg, wordrecg,
ropes, msgs, platform, os, condsyms, idents, renderer, types, extccomp, math, ropes, msgs, platform, os, condsyms, idents, renderer, types, extccomp, math,
magicsys, nversion, nimsets, parser, times, passes, rodread, vmdef, magicsys, nversion, nimsets, parser, times, passes, rodread, vmdef,
modulegraphs, configuration modulegraphs, lineinfos
type type
TOptionEntry* = object # entries to put on a stack for pragma parsing TOptionEntry* = object # entries to put on a stack for pragma parsing

View file

@ -26,10 +26,10 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
flags: TExprFlags = {}): PNode = flags: TExprFlags = {}): PNode =
markUsed(c.config, n.info, s, c.graph.usageSym) markUsed(c.config, n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
pushInfoContext(n.info) pushInfoContext(c.config, n.info)
result = evalTemplate(n, s, getCurrOwner(c), c.config, efFromHlo in flags) result = evalTemplate(n, s, getCurrOwner(c), c.config, efFromHlo in flags)
if efNoSemCheck notin flags: result = semAfterMacroCall(c, n, result, s, flags) if efNoSemCheck notin flags: result = semAfterMacroCall(c, n, result, s, flags)
popInfoContext() popInfoContext(c.config)
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
@ -742,7 +742,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
# This is a proc variable, apply normal overload resolution # This is a proc variable, apply normal overload resolution
let m = resolveIndirectCall(c, n, nOrig, t) let m = resolveIndirectCall(c, n, nOrig, t)
if m.state != csMatch: if m.state != csMatch:
if errorOutputs == {}: if c.config.m.errorOutputs == {}:
# speed up error generation: # speed up error generation:
globalError(c.config, n.info, "type mismatch") globalError(c.config, n.info, "type mismatch")
return c.graph.emptyNode return c.graph.emptyNode
@ -1082,7 +1082,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
when defined(nimsuggest): when defined(nimsuggest):
if c.config.cmd == cmdIdeTools: if c.config.cmd == cmdIdeTools:
suggestExpr(c, n) suggestExpr(c, n)
if exactEquals(gTrackPos, n[1].info): suggestExprNoCheck(c, n) if exactEquals(c.config.m.trackPos, n[1].info): suggestExprNoCheck(c, n)
var s = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared, checkModule}) var s = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared, checkModule})
if s != nil: if s != nil:
@ -1783,9 +1783,9 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
openScope(c) openScope(c)
let oldOwnerLen = len(c.graph.owners) let oldOwnerLen = len(c.graph.owners)
let oldGenerics = c.generics let oldGenerics = c.generics
let oldErrorOutputs = errorOutputs let oldErrorOutputs = c.config.m.errorOutputs
if efExplain notin flags: errorOutputs = {} if efExplain notin flags: c.config.m.errorOutputs = {}
let oldContextLen = msgs.getInfoContextLen() let oldContextLen = msgs.getInfoContextLen(c.config)
let oldInGenericContext = c.inGenericContext let oldInGenericContext = c.inGenericContext
let oldInUnrolledContext = c.inUnrolledContext let oldInUnrolledContext = c.inUnrolledContext
@ -1807,10 +1807,10 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
c.inGenericInst = oldInGenericInst c.inGenericInst = oldInGenericInst
c.inStaticContext = oldInStaticContext c.inStaticContext = oldInStaticContext
c.p = oldProcCon c.p = oldProcCon
msgs.setInfoContextLen(oldContextLen) msgs.setInfoContextLen(c.config, oldContextLen)
setLen(c.graph.owners, oldOwnerLen) setLen(c.graph.owners, oldOwnerLen)
c.currentScope = oldScope c.currentScope = oldScope
errorOutputs = oldErrorOutputs c.config.m.errorOutputs = oldErrorOutputs
c.config.errorCounter = oldErrorCount c.config.errorCounter = oldErrorCount
c.config.errorMax = oldErrorMax c.config.errorMax = oldErrorMax
@ -2309,7 +2309,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# check if it is an expression macro: # check if it is an expression macro:
checkMinSonsLen(n, 1, c.config) checkMinSonsLen(n, 1, c.config)
#when defined(nimsuggest): #when defined(nimsuggest):
# if gIdeCmd == ideCon and gTrackPos == n.info: suggestExprNoCheck(c, n) # if gIdeCmd == ideCon and c.config.m.trackPos == n.info: suggestExprNoCheck(c, n)
let mode = if nfDotField in n.flags: {} else: {checkUndeclared} let mode = if nfDotField in n.flags: {} else: {checkUndeclared}
var s = qualifiedLookUp(c, n.sons[0], mode) var s = qualifiedLookUp(c, n.sons[0], mode)
if s != nil: if s != nil:

View file

@ -13,7 +13,7 @@
import import
strutils, options, ast, astalgo, trees, treetab, nimsets, times, strutils, options, ast, astalgo, trees, treetab, nimsets, times,
nversion, platform, math, msgs, os, condsyms, idents, renderer, types, nversion, platform, math, msgs, os, condsyms, idents, renderer, types,
commands, magicsys, modulegraphs, strtabs commands, magicsys, modulegraphs, strtabs, lineinfos
proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode = proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
case skipTypes(n.typ, abstractVarRange).kind case skipTypes(n.typ, abstractVarRange).kind

View file

@ -55,7 +55,7 @@ template macroToExpandSym(s): untyped =
proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
ctx: var GenericCtx; fromDotExpr=false): PNode = ctx: var GenericCtx; fromDotExpr=false): PNode =
semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody) semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
case s.kind case s.kind
of skUnknown: of skUnknown:
@ -129,7 +129,7 @@ proc newDot(n, b: PNode): PNode =
proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags, proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
ctx: var GenericCtx; isMacro: var bool): PNode = ctx: var GenericCtx; isMacro: var bool): PNode =
assert n.kind == nkDotExpr assert n.kind == nkDotExpr
semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody) semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
let luf = if withinMixin notin flags: {checkUndeclared, checkModule} else: {checkModule} let luf = if withinMixin notin flags: {checkUndeclared, checkModule} else: {checkModule}
@ -170,7 +170,7 @@ proc semGenericStmt(c: PContext, n: PNode,
if withinTypeDesc in flags: inc c.inTypeContext if withinTypeDesc in flags: inc c.inTypeContext
#if conf.cmd == cmdIdeTools: suggestStmt(c, n) #if conf.cmd == cmdIdeTools: suggestStmt(c, n)
semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody) semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
case n.kind case n.kind
of nkIdent, nkAccQuoted: of nkIdent, nkAccQuoted:

View file

@ -159,13 +159,13 @@ proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
var oldPrc = c.generics[i].inst.sym var oldPrc = c.generics[i].inst.sym
pushProcCon(c, oldPrc) pushProcCon(c, oldPrc)
pushOwner(c, oldPrc) pushOwner(c, oldPrc)
pushInfoContext(oldPrc.info) pushInfoContext(c.config, oldPrc.info)
openScope(c) openScope(c)
var n = oldPrc.ast var n = oldPrc.ast
n.sons[bodyPos] = copyTree(s.getBody) n.sons[bodyPos] = copyTree(s.getBody)
instantiateBody(c, n, oldPrc.typ.n, oldPrc, s) instantiateBody(c, n, oldPrc.typ.n, oldPrc, s)
closeScope(c) closeScope(c)
popInfoContext() popInfoContext(c.config)
popOwner(c) popOwner(c)
popProcCon(c) popProcCon(c)
@ -236,7 +236,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
# at this point semtypinst have to become part of sem, because it # at this point semtypinst have to become part of sem, because it
# will need to use openScope, addDecl, etc. # will need to use openScope, addDecl, etc.
#addDecl(c, prc) #addDecl(c, prc)
pushInfoContext(info) pushInfoContext(c.config, info)
var typeMap = initLayeredTypeMap(pt) var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(c, addr(typeMap), info, nil) var cl = initTypeVars(c, addr(typeMap), info, nil)
var result = instCopyType(cl, prc.typ) var result = instCopyType(cl, prc.typ)
@ -278,7 +278,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
skipIntLiteralParams(result) skipIntLiteralParams(result)
prc.typ = result prc.typ = result
popInfoContext() popInfoContext(c.config)
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
info: TLineInfo): PSym = info: TLineInfo): PSym =
@ -309,7 +309,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
let gp = n.sons[genericParamsPos] let gp = n.sons[genericParamsPos]
internalAssert c.config, gp.kind != nkEmpty internalAssert c.config, gp.kind != nkEmpty
n.sons[namePos] = newSymNode(result) n.sons[namePos] = newSymNode(result)
pushInfoContext(info) pushInfoContext(c.config, info)
var entry = TInstantiation.new var entry = TInstantiation.new
entry.sym = result entry.sym = result
# we need to compare both the generic types and the concrete types: # we need to compare both the generic types and the concrete types:
@ -353,7 +353,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
else: else:
result = oldPrc result = oldPrc
popProcCon(c) popProcCon(c)
popInfoContext() popInfoContext(c.config)
closeScope(c) # close scope for parameters closeScope(c) # close scope for parameters
popOwner(c) popOwner(c)
c.currentScope = oldScope c.currentScope = oldScope

View file

@ -76,7 +76,7 @@ proc semInstantiationInfo(c: PContext, n: PNode): PNode =
result = newNodeIT(nkTupleConstr, n.info, n.typ) result = newNodeIT(nkTupleConstr, n.info, n.typ)
let idx = expectIntLit(c, n.sons[1]) let idx = expectIntLit(c, n.sons[1])
let useFullPaths = expectIntLit(c, n.sons[2]) let useFullPaths = expectIntLit(c, n.sons[2])
let info = getInfoContext(idx) let info = getInfoContext(c.config, idx)
var filename = newNodeIT(nkStrLit, n.info, getSysType(c.graph, n.info, tyString)) var filename = newNodeIT(nkStrLit, n.info, getSysType(c.graph, n.info, tyString))
filename.strVal = if useFullPaths != 0: toFullPath(c.config, info) else: toFilename(c.config, info) filename.strVal = if useFullPaths != 0: toFullPath(c.config, info) else: toFilename(c.config, info)
var line = newNodeIT(nkIntLit, n.info, getSysType(c.graph, n.info, tyInt)) var line = newNodeIT(nkIntLit, n.info, getSysType(c.graph, n.info, tyInt))

View file

@ -9,7 +9,7 @@
import import
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
wordrecg, strutils, options, guards, writetracking, configuration, wordrecg, strutils, options, guards, writetracking, lineinfos,
modulegraphs modulegraphs
when defined(useDfa): when defined(useDfa):
@ -859,9 +859,9 @@ proc checkRaisesSpec(g: ModuleGraph; spec, real: PNode, msg: string, hints: bool
used.incl(s) used.incl(s)
break search break search
# XXX call graph analysis would be nice here! # XXX call graph analysis would be nice here!
pushInfoContext(spec.info) pushInfoContext(g.config, spec.info)
localError(g.config, r.info, errGenerated, msg & typeToString(r.typ)) localError(g.config, r.info, errGenerated, msg & typeToString(r.typ))
popInfoContext() popInfoContext(g.config)
# hint about unnecessarily listed exception types: # hint about unnecessarily listed exception types:
if hints: if hints:
for s in 0 ..< spec.len: for s in 0 ..< spec.len:

View file

@ -89,7 +89,7 @@ proc semWhile(c: PContext, n: PNode): PNode =
result.typ = c.enforceVoidContext result.typ = c.enforceVoidContext
proc toCover(c: PContext, t: PType): BiggestInt = proc toCover(c: PContext, t: PType): BiggestInt =
var t2 = skipTypes(t, abstractVarRange-{tyTypeDesc}) let t2 = skipTypes(t, abstractVarRange-{tyTypeDesc})
if t2.kind == tyEnum and enumHasHoles(t2): if t2.kind == tyEnum and enumHasHoles(t2):
result = sonsLen(t2.n) result = sonsLen(t2.n)
else: else:
@ -201,7 +201,7 @@ proc semCase(c: PContext, n: PNode): PNode =
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
var x = n.sons[i] var x = n.sons[i]
when defined(nimsuggest): when defined(nimsuggest):
if c.config.ideCmd == ideSug and exactEquals(gTrackPos, x.info) and caseTyp.kind == tyEnum: if c.config.ideCmd == ideSug and exactEquals(c.config.m.trackPos, x.info) and caseTyp.kind == tyEnum:
suggestEnum(c, x, caseTyp) suggestEnum(c, x, caseTyp)
case x.kind case x.kind
of nkOfBranch: of nkOfBranch:
@ -1396,14 +1396,14 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
localError(c.config, n.info, errGenerated, localError(c.config, n.info, errGenerated,
"'destroy' or 'deepCopy' expected for 'override'") "'destroy' or 'deepCopy' expected for 'override'")
proc cursorInProcAux(n: PNode): bool = proc cursorInProcAux(conf: ConfigRef; n: PNode): bool =
if inCheckpoint(n.info) != cpNone: return true if inCheckpoint(n.info, conf.m.trackPos) != cpNone: return true
for i in 0..<n.safeLen: for i in 0..<n.safeLen:
if cursorInProcAux(n[i]): return true if cursorInProcAux(conf, n[i]): return true
proc cursorInProc(n: PNode): bool = proc cursorInProc(conf: ConfigRef; n: PNode): bool =
if n.info.fileIndex == gTrackPos.fileIndex: if n.info.fileIndex == conf.m.trackPos.fileIndex:
result = cursorInProcAux(n) result = cursorInProcAux(conf, n)
type type
TProcCompilationSteps = enum TProcCompilationSteps = enum
@ -1583,7 +1583,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
# only used for overload resolution (there is no instantiation of # only used for overload resolution (there is no instantiation of
# the symbol, so we must process the body now) # the symbol, so we must process the body now)
if not usePseudoGenerics and c.config.ideCmd in {ideSug, ideCon} and not if not usePseudoGenerics and c.config.ideCmd in {ideSug, ideCon} and not
cursorInProc(n.sons[bodyPos]): cursorInProc(c.config, n.sons[bodyPos]):
discard "speed up nimsuggest" discard "speed up nimsuggest"
if s.kind == skMethod: semMethodPrototype(c, s, n) if s.kind == skMethod: semMethodPrototype(c, s, n)
else: else:

View file

@ -305,7 +305,7 @@ proc semTemplBodySons(c: var TemplCtx, n: PNode): PNode =
proc semTemplBody(c: var TemplCtx, n: PNode): PNode = proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
result = n result = n
semIdeForTemplateOrGenericCheck(n, c.cursorInBody) semIdeForTemplateOrGenericCheck(c.c.config, n, c.cursorInBody)
case n.kind case n.kind
of nkIdent: of nkIdent:
if n.ident.id in c.toInject: return n if n.ident.id in c.toInject: return n
@ -518,7 +518,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode = proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
result = n result = n
semIdeForTemplateOrGenericCheck(n, c.cursorInBody) semIdeForTemplateOrGenericCheck(c.c.config, n, c.cursorInBody)
case n.kind case n.kind
of nkIdent: of nkIdent:
let s = qualifiedLookUp(c.c, n, {}) let s = qualifiedLookUp(c.c, n, {})

View file

@ -9,7 +9,8 @@
# This module does the instantiation of generic types. # This module does the instantiation of generic types.
import ast, astalgo, msgs, types, magicsys, semdata, renderer, options import ast, astalgo, msgs, types, magicsys, semdata, renderer, options,
lineinfos
const const
tfInstClearedFlags = {tfHasMeta, tfUnresolved} tfInstClearedFlags = {tfHasMeta, tfUnresolved}
@ -568,35 +569,35 @@ proc replaceTypesInBody*(p: PContext, pt: TIdTable, n: PNode;
var typeMap = initLayeredTypeMap(pt) var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(p, addr(typeMap), n.info, owner) var cl = initTypeVars(p, addr(typeMap), n.info, owner)
cl.allowMetaTypes = allowMetaTypes cl.allowMetaTypes = allowMetaTypes
pushInfoContext(n.info) pushInfoContext(p.config, n.info)
result = replaceTypeVarsN(cl, n) result = replaceTypeVarsN(cl, n)
popInfoContext() popInfoContext(p.config)
proc replaceTypesForLambda*(p: PContext, pt: TIdTable, n: PNode; proc replaceTypesForLambda*(p: PContext, pt: TIdTable, n: PNode;
original, new: PSym): PNode = original, new: PSym): PNode =
var typeMap = initLayeredTypeMap(pt) var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(p, addr(typeMap), n.info, original) var cl = initTypeVars(p, addr(typeMap), n.info, original)
idTablePut(cl.symMap, original, new) idTablePut(cl.symMap, original, new)
pushInfoContext(n.info) pushInfoContext(p.config, n.info)
result = replaceTypeVarsN(cl, n) result = replaceTypeVarsN(cl, n)
popInfoContext() popInfoContext(p.config)
proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo, proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo,
t: PType): PType = t: PType): PType =
var typeMap = initLayeredTypeMap(pt) var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(p, addr(typeMap), info, nil) var cl = initTypeVars(p, addr(typeMap), info, nil)
pushInfoContext(info) pushInfoContext(p.config, info)
result = replaceTypeVarsT(cl, t) result = replaceTypeVarsT(cl, t)
popInfoContext() popInfoContext(p.config)
proc prepareMetatypeForSigmatch*(p: PContext, pt: TIdTable, info: TLineInfo, proc prepareMetatypeForSigmatch*(p: PContext, pt: TIdTable, info: TLineInfo,
t: PType): PType = t: PType): PType =
var typeMap = initLayeredTypeMap(pt) var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(p, addr(typeMap), info, nil) var cl = initTypeVars(p, addr(typeMap), info, nil)
cl.allowMetaTypes = true cl.allowMetaTypes = true
pushInfoContext(info) pushInfoContext(p.config, info)
result = replaceTypeVarsT(cl, t) result = replaceTypeVarsT(cl, t)
popInfoContext() popInfoContext(p.config)
template generateTypeInstance*(p: PContext, pt: TIdTable, arg: PNode, template generateTypeInstance*(p: PContext, pt: TIdTable, arg: PNode,
t: PType): untyped = t: PType): untyped =

View file

@ -11,7 +11,7 @@
import import
times, commands, options, msgs, nimconf, times, commands, options, msgs, nimconf,
extccomp, strutils, os, platform, parseopt, idents, configuration extccomp, strutils, os, platform, parseopt, idents, lineinfos
when useCaas: when useCaas:
import net import net
@ -71,7 +71,7 @@ proc serve*(cache: IdentCache; action: proc (cache: IdentCache){.nimcall.}; conf
var inp = "".TaintedString var inp = "".TaintedString
server.listen() server.listen()
var stdoutSocket = newSocket() var stdoutSocket = newSocket()
msgs.writelnHook = proc (line: string) = config.writelnHook = proc (line: string) =
stdoutSocket.send(line & "\c\L") stdoutSocket.send(line & "\c\L")
while true: while true:

View file

@ -13,7 +13,7 @@
import import
intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst, intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
magicsys, condsyms, idents, lexer, options, parampatterns, strutils, trees, magicsys, condsyms, idents, lexer, options, parampatterns, strutils, trees,
nimfix.pretty nimfix / pretty, lineinfos
when not defined(noDocgen): when not defined(noDocgen):
import docgen import docgen
@ -722,7 +722,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
addDecl(c, param) addDecl(c, param)
var var
oldWriteHook: type(writelnHook) oldWriteHook: type(m.c.config.writelnHook)
diagnostics: seq[string] diagnostics: seq[string]
errorPrefix: string errorPrefix: string
flags: TExprFlags = {} flags: TExprFlags = {}
@ -730,12 +730,12 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
sfExplain in typeClass.sym.flags sfExplain in typeClass.sym.flags
if collectDiagnostics: if collectDiagnostics:
oldWriteHook = writelnHook oldWriteHook = m.c.config.writelnHook
# XXX: we can't write to m.diagnostics directly, because # XXX: we can't write to m.diagnostics directly, because
# Nim doesn't support capturing var params in closures # Nim doesn't support capturing var params in closures
diagnostics = @[] diagnostics = @[]
flags = {efExplain} flags = {efExplain}
writelnHook = proc (s: string) = m.c.config.writelnHook = proc (s: string) =
if errorPrefix == nil: errorPrefix = typeClass.sym.name.s & ":" if errorPrefix == nil: errorPrefix = typeClass.sym.name.s & ":"
let msg = s.replace("Error:", errorPrefix) let msg = s.replace("Error:", errorPrefix)
if oldWriteHook != nil: oldWriteHook msg if oldWriteHook != nil: oldWriteHook msg
@ -744,7 +744,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
var checkedBody = c.semTryExpr(c, body.copyTree, flags) var checkedBody = c.semTryExpr(c, body.copyTree, flags)
if collectDiagnostics: if collectDiagnostics:
writelnHook = oldWriteHook m.c.config.writelnHook = oldWriteHook
for msg in diagnostics: for msg in diagnostics:
m.diagnostics.safeAdd msg m.diagnostics.safeAdd msg
m.diagnosticsEnabled = true m.diagnosticsEnabled = true

View file

@ -32,7 +32,7 @@
# included from sigmatch.nim # included from sigmatch.nim
import algorithm, prefixmatches, configuration import algorithm, prefixmatches, lineinfos
from wordrecg import wDeprecated from wordrecg import wDeprecated
when defined(nimsuggest): when defined(nimsuggest):
@ -41,31 +41,6 @@ when defined(nimsuggest):
const const
sep = '\t' sep = '\t'
type
Suggest* = ref object
section*: IdeCmd
qualifiedPath*: seq[string]
name*: PIdent # not used beyond sorting purposes; name is also
# part of 'qualifiedPath'
filePath*: string
line*: int # Starts at 1
column*: int # Starts at 0
doc*: string # Not escaped (yet)
symkind*: TSymKind
forth*: string # type
quality*: range[0..100] # matching quality
isGlobal*: bool # is a global variable
contextFits*: bool # type/non-type context matches
prefix*: PrefixMatch
scope*, localUsages*, globalUsages*: int # more usages is better
tokenLen*: int
Suggestions* = seq[Suggest]
var
suggestionResultHook*: proc (result: Suggest) {.closure.}
suggestVersion*: int
suggestMaxResults* = 10_000
#template sectionSuggest(): expr = "##begin\n" & getStackTrace() & "##end\n" #template sectionSuggest(): expr = "##begin\n" & getStackTrace() & "##end\n"
template origModuleName(m: PSym): string = m.name.s template origModuleName(m: PSym): string = m.name.s
@ -104,7 +79,7 @@ proc cmpSuggestions(a, b: Suggest): int =
cf globalUsages cf globalUsages
# if all is equal, sort alphabetically for deterministic output, # if all is equal, sort alphabetically for deterministic output,
# independent of hashing order: # independent of hashing order:
result = cmp(a.name.s, b.name.s) result = cmp(a.name[], b.name[])
proc symToSuggest(conf: ConfigRef; s: PSym, isLocal: bool, section: IdeCmd, info: TLineInfo; proc symToSuggest(conf: ConfigRef; s: PSym, isLocal: bool, section: IdeCmd, info: TLineInfo;
quality: range[0..100]; prefix: PrefixMatch; quality: range[0..100]; prefix: PrefixMatch;
@ -117,14 +92,14 @@ proc symToSuggest(conf: ConfigRef; s: PSym, isLocal: bool, section: IdeCmd, info
result.prefix = prefix result.prefix = prefix
result.contextFits = inTypeContext == (s.kind in {skType, skGenericParam}) result.contextFits = inTypeContext == (s.kind in {skType, skGenericParam})
result.scope = scope result.scope = scope
result.name = s.name result.name = addr s.name.s
when defined(nimsuggest): when defined(nimsuggest):
result.globalUsages = s.allUsages.len result.globalUsages = s.allUsages.len
var c = 0 var c = 0
for u in s.allUsages: for u in s.allUsages:
if u.fileIndex == info.fileIndex: inc c if u.fileIndex == info.fileIndex: inc c
result.localUsages = c result.localUsages = c
result.symkind = s.kind result.symkind = byte s.kind
if optIdeTerse notin conf.globalOptions: if optIdeTerse notin conf.globalOptions:
result.qualifiedPath = @[] result.qualifiedPath = @[]
if not isLocal and s.kind != skModule: if not isLocal and s.kind != skModule:
@ -146,17 +121,18 @@ proc symToSuggest(conf: ConfigRef; s: PSym, isLocal: bool, section: IdeCmd, info
result.filePath = toFullPath(conf, infox) result.filePath = toFullPath(conf, infox)
result.line = toLinenumber(infox) result.line = toLinenumber(infox)
result.column = toColumn(infox) result.column = toColumn(infox)
result.version = conf.suggestVersion
proc `$`*(suggest: Suggest): string = proc `$`*(suggest: Suggest): string =
result = $suggest.section result = $suggest.section
result.add(sep) result.add(sep)
if suggest.section == ideHighlight: if suggest.section == ideHighlight:
if suggest.symkind == skVar and suggest.isGlobal: if suggest.symkind.TSymKind == skVar and suggest.isGlobal:
result.add("skGlobalVar") result.add("skGlobalVar")
elif suggest.symkind == skLet and suggest.isGlobal: elif suggest.symkind.TSymKind == skLet and suggest.isGlobal:
result.add("skGlobalLet") result.add("skGlobalLet")
else: else:
result.add($suggest.symkind) result.add($suggest.symkind.TSymKind)
result.add(sep) result.add(sep)
result.add($suggest.line) result.add($suggest.line)
result.add(sep) result.add(sep)
@ -164,9 +140,9 @@ proc `$`*(suggest: Suggest): string =
result.add(sep) result.add(sep)
result.add($suggest.tokenLen) result.add($suggest.tokenLen)
else: else:
result.add($suggest.symkind) result.add($suggest.symkind.TSymKind)
result.add(sep) result.add(sep)
if suggest.qualifiedPath != nil: if suggest.qualifiedPath.len != 0:
result.add(suggest.qualifiedPath.join(".")) result.add(suggest.qualifiedPath.join("."))
result.add(sep) result.add(sep)
result.add(suggest.forth) result.add(suggest.forth)
@ -179,18 +155,18 @@ proc `$`*(suggest: Suggest): string =
result.add(sep) result.add(sep)
when not defined(noDocgen): when not defined(noDocgen):
result.add(suggest.doc.escape) result.add(suggest.doc.escape)
if suggestVersion == 0: if suggest.version == 0:
result.add(sep) result.add(sep)
result.add($suggest.quality) result.add($suggest.quality)
if suggest.section == ideSug: if suggest.section == ideSug:
result.add(sep) result.add(sep)
result.add($suggest.prefix) result.add($suggest.prefix)
proc suggestResult(s: Suggest) = proc suggestResult(conf: ConfigRef; s: Suggest) =
if not isNil(suggestionResultHook): if not isNil(conf.suggestionResultHook):
suggestionResultHook(s) conf.suggestionResultHook(s)
else: else:
suggestWriteln($s) conf.suggestWriteln($s)
proc produceOutput(a: var Suggestions; conf: ConfigRef) = proc produceOutput(a: var Suggestions; conf: ConfigRef) =
if conf.ideCmd in {ideSug, ideCon}: if conf.ideCmd in {ideSug, ideCon}:
@ -198,13 +174,13 @@ proc produceOutput(a: var Suggestions; conf: ConfigRef) =
when defined(debug): when defined(debug):
# debug code # debug code
writeStackTrace() writeStackTrace()
if a.len > suggestMaxResults: a.setLen(suggestMaxResults) if a.len > conf.suggestMaxResults: a.setLen(conf.suggestMaxResults)
if not isNil(suggestionResultHook): if not isNil(conf.suggestionResultHook):
for s in a: for s in a:
suggestionResultHook(s) conf.suggestionResultHook(s)
else: else:
for s in a: for s in a:
suggestWriteln($s) conf.suggestWriteln($s)
proc filterSym(s: PSym; prefix: PNode; res: var PrefixMatch): bool {.inline.} = proc filterSym(s: PSym; prefix: PNode; res: var PrefixMatch): bool {.inline.} =
proc prefixMatch(s: PSym; n: PNode): PrefixMatch = proc prefixMatch(s: PSym; n: PNode): PrefixMatch =
@ -340,7 +316,7 @@ proc suggestFieldAccess(c: PContext, n, field: PNode, outputs: var Suggestions)
var typ = n.typ var typ = n.typ
var pm: PrefixMatch var pm: PrefixMatch
when defined(nimsuggest): when defined(nimsuggest):
if n.kind == nkSym and n.sym.kind == skError and suggestVersion == 0: if n.kind == nkSym and n.sym.kind == skError and c.config.suggestVersion == 0:
# consider 'foo.|' where 'foo' is some not imported module. # consider 'foo.|' where 'foo' is some not imported module.
let fullPath = findModule(c.config, n.sym.name.s, toFullPath(c.config, n.info)) let fullPath = findModule(c.config, n.sym.name.s, toFullPath(c.config, n.info))
if fullPath.len == 0: if fullPath.len == 0:
@ -397,17 +373,17 @@ type
TCheckPointResult* = enum TCheckPointResult* = enum
cpNone, cpFuzzy, cpExact cpNone, cpFuzzy, cpExact
proc inCheckpoint*(current: TLineInfo): TCheckPointResult = proc inCheckpoint*(current, trackPos: TLineInfo): TCheckPointResult =
if current.fileIndex == gTrackPos.fileIndex: if current.fileIndex == trackPos.fileIndex:
if current.line == gTrackPos.line and if current.line == trackPos.line and
abs(current.col-gTrackPos.col) < 4: abs(current.col-trackPos.col) < 4:
return cpExact return cpExact
if current.line >= gTrackPos.line: if current.line >= trackPos.line:
return cpFuzzy return cpFuzzy
proc isTracked*(current: TLineInfo, tokenLen: int): bool = proc isTracked*(current, trackPos: TLineInfo, tokenLen: int): bool =
if current.fileIndex==gTrackPos.fileIndex and current.line==gTrackPos.line: if current.fileIndex==trackPos.fileIndex and current.line==trackPos.line:
let col = gTrackPos.col let col = trackPos.col
if col >= current.col and col <= current.col+tokenLen-1: if col >= current.col and col <= current.col+tokenLen-1:
return true return true
@ -425,30 +401,27 @@ when defined(nimsuggest):
if infoB.infoToInt == infoAsInt: return if infoB.infoToInt == infoAsInt: return
s.allUsages.add(info) s.allUsages.add(info)
var
lastLineInfo*: TLineInfo # XXX global here
proc findUsages(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) = proc findUsages(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) =
if suggestVersion == 1: if conf.suggestVersion == 1:
if usageSym == nil and isTracked(info, s.name.s.len): if usageSym == nil and isTracked(info, conf.m.trackPos, s.name.s.len):
usageSym = s usageSym = s
suggestResult(symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0)) suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0))
elif s == usageSym: elif s == usageSym:
if lastLineInfo != info: if conf.lastLineInfo != info:
suggestResult(symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0)) suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0))
lastLineInfo = info conf.lastLineInfo = info
when defined(nimsuggest): when defined(nimsuggest):
proc listUsages*(conf: ConfigRef; s: PSym) = proc listUsages*(conf: ConfigRef; s: PSym) =
#echo "usages ", len(s.allUsages) #echo "usages ", len(s.allUsages)
for info in s.allUsages: for info in s.allUsages:
let x = if info == s.info and info.col == s.info.col: ideDef else: ideUse let x = if info == s.info and info.col == s.info.col: ideDef else: ideUse
suggestResult(symToSuggest(conf, s, isLocal=false, x, info, 100, PrefixMatch.None, false, 0)) suggestResult(conf, symToSuggest(conf, s, isLocal=false, x, info, 100, PrefixMatch.None, false, 0))
proc findDefinition(conf: ConfigRef; info: TLineInfo; s: PSym) = proc findDefinition(conf: ConfigRef; info: TLineInfo; s: PSym) =
if s.isNil: return if s.isNil: return
if isTracked(info, s.name.s.len): if isTracked(info, conf.m.trackPos, s.name.s.len):
suggestResult(symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0)) suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0))
suggestQuit() suggestQuit()
proc ensureIdx[T](x: var T, y: int) = proc ensureIdx[T](x: var T, y: int) =
@ -460,7 +433,7 @@ proc ensureSeq[T](x: var seq[T]) =
proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym; isDecl=true) {.inline.} = proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym; isDecl=true) {.inline.} =
## misnamed: should be 'symDeclared' ## misnamed: should be 'symDeclared'
when defined(nimsuggest): when defined(nimsuggest):
if suggestVersion == 0: if conf.suggestVersion == 0:
if s.allUsages.isNil: if s.allUsages.isNil:
s.allUsages = @[info] s.allUsages = @[info]
else: else:
@ -471,14 +444,14 @@ proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym;
elif conf.ideCmd == ideDef: elif conf.ideCmd == ideDef:
findDefinition(conf, info, s) findDefinition(conf, info, s)
elif conf.ideCmd == ideDus and s != nil: elif conf.ideCmd == ideDus and s != nil:
if isTracked(info, s.name.s.len): if isTracked(info, conf.m.trackPos, s.name.s.len):
suggestResult(symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0)) suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0))
findUsages(conf, info, s, usageSym) findUsages(conf, info, s, usageSym)
elif conf.ideCmd == ideHighlight and info.fileIndex == gTrackPos.fileIndex: elif conf.ideCmd == ideHighlight and info.fileIndex == conf.m.trackPos.fileIndex:
suggestResult(symToSuggest(conf, s, isLocal=false, ideHighlight, info, 100, PrefixMatch.None, false, 0)) suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideHighlight, info, 100, PrefixMatch.None, false, 0))
elif conf.ideCmd == ideOutline and info.fileIndex == gTrackPos.fileIndex and elif conf.ideCmd == ideOutline and info.fileIndex == conf.m.trackPos.fileIndex and
isDecl: isDecl:
suggestResult(symToSuggest(conf, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0)) suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0))
proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) = proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) =
if s.kind in routineKinds: if s.kind in routineKinds:
@ -519,14 +492,14 @@ proc sugExpr(c: PContext, n: PNode, outputs: var Suggestions) =
# of the next line, so we check the 'field' is actually on the same # of the next line, so we check the 'field' is actually on the same
# line as the object to prevent this from happening: # line as the object to prevent this from happening:
let prefix = if n.len == 2 and n[1].info.line == n[0].info.line and let prefix = if n.len == 2 and n[1].info.line == n[0].info.line and
not gTrackPosAttached: n[1] else: nil not c.config.m.trackPosAttached: n[1] else: nil
suggestFieldAccess(c, obj, prefix, outputs) suggestFieldAccess(c, obj, prefix, outputs)
#if optIdeDebug in gGlobalOptions: #if optIdeDebug in gGlobalOptions:
# echo "expression ", renderTree(obj), " has type ", typeToString(obj.typ) # echo "expression ", renderTree(obj), " has type ", typeToString(obj.typ)
#writeStackTrace() #writeStackTrace()
else: else:
let prefix = if gTrackPosAttached: nil else: n let prefix = if c.config.m.trackPosAttached: nil else: n
suggestEverything(c, n, prefix, outputs) suggestEverything(c, n, prefix, outputs)
proc suggestExprNoCheck*(c: PContext, n: PNode) = proc suggestExprNoCheck*(c: PContext, n: PNode) =
@ -555,10 +528,10 @@ proc suggestExprNoCheck*(c: PContext, n: PNode) =
suggestQuit() suggestQuit()
proc suggestExpr*(c: PContext, n: PNode) = proc suggestExpr*(c: PContext, n: PNode) =
if exactEquals(gTrackPos, n.info): suggestExprNoCheck(c, n) if exactEquals(c.config.m.trackPos, n.info): suggestExprNoCheck(c, n)
proc suggestDecl*(c: PContext, n: PNode; s: PSym) = proc suggestDecl*(c: PContext, n: PNode; s: PSym) =
let attached = gTrackPosAttached let attached = c.config.m.trackPosAttached
if attached: inc(c.inTypeContext) if attached: inc(c.inTypeContext)
defer: defer:
if attached: dec(c.inTypeContext) if attached: dec(c.inTypeContext)
@ -574,7 +547,7 @@ proc suggestEnum*(c: PContext; n: PNode; t: PType) =
if outputs.len > 0: suggestQuit() if outputs.len > 0: suggestQuit()
proc suggestSentinel*(c: PContext) = proc suggestSentinel*(c: PContext) =
if c.config.ideCmd != ideSug or c.module.position != gTrackPos.fileIndex.int32: return if c.config.ideCmd != ideSug or c.module.position != c.config.m.trackPos.fileIndex.int32: return
if c.compilesContextId > 0: return if c.compilesContextId > 0: return
inc(c.compilesContextId) inc(c.compilesContextId)
var outputs: Suggestions = @[] var outputs: Suggestions = @[]
@ -587,7 +560,9 @@ proc suggestSentinel*(c: PContext) =
for it in items(scope.symbols): for it in items(scope.symbols):
var pm: PrefixMatch var pm: PrefixMatch
if filterSymNoOpr(it, nil, pm): if filterSymNoOpr(it, nil, pm):
outputs.add(symToSuggest(c.config, it, isLocal = isLocal, ideSug, newLineInfo(gTrackPos.fileIndex, -1, -1), 0, PrefixMatch.None, false, scopeN)) outputs.add(symToSuggest(c.config, it, isLocal = isLocal, ideSug,
newLineInfo(c.config.m.trackPos.fileIndex, -1, -1), 0,
PrefixMatch.None, false, scopeN))
dec(c.compilesContextId) dec(c.compilesContextId)
produceOutput(outputs, c.config) produceOutput(outputs, c.config)

View file

@ -11,7 +11,7 @@
import import
strutils, llstream, ast, astalgo, idents, lexer, options, msgs, parser, strutils, llstream, ast, astalgo, idents, lexer, options, msgs, parser,
filters, filter_tmpl, renderer, configuration filters, filter_tmpl, renderer, lineinfos
type type
TFilterKind* = enum TFilterKind* = enum

View file

@ -22,7 +22,7 @@ import
intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os, intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os,
idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread, idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread,
lambdalifting, sempass2, lowerings, lookups, destroyer, liftlocals, lambdalifting, sempass2, lowerings, lookups, destroyer, liftlocals,
modulegraphs modulegraphs, lineinfos
type type
PTransNode* = distinct PNode PTransNode* = distinct PNode
@ -598,7 +598,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
idNodeTablePut(newC.mapping, formal, temp) idNodeTablePut(newC.mapping, formal, temp)
var body = iter.getBody.copyTree var body = iter.getBody.copyTree
pushInfoContext(n.info) pushInfoContext(c.graph.config, n.info)
# XXX optimize this somehow. But the check "c.inlining" is not correct: # XXX optimize this somehow. But the check "c.inlining" is not correct:
var symMap: TIdTable var symMap: TIdTable
initIdTable symMap initIdTable symMap
@ -608,7 +608,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
add(stmtList, transform(c, body)) add(stmtList, transform(c, body))
#findWrongOwners(c, stmtList.pnode) #findWrongOwners(c, stmtList.pnode)
dec(c.inlining) dec(c.inlining)
popInfoContext() popInfoContext(c.graph.config)
popTransCon(c) popTransCon(c)
# echo "transformed: ", stmtList.PNode.renderTree # echo "transformed: ", stmtList.PNode.renderTree

View file

@ -10,7 +10,8 @@
# this module contains routines for accessing and iterating over types # this module contains routines for accessing and iterating over types
import import
intsets, ast, astalgo, trees, msgs, strutils, platform, renderer, options intsets, ast, astalgo, trees, msgs, strutils, platform, renderer, options,
lineinfos
type type
TPreferedDesc* = enum TPreferedDesc* = enum

View file

@ -19,7 +19,7 @@ import ast except getstr
import import
strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes, strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes,
parser, vmdeps, idents, trees, renderer, options, transf, parseutils, parser, vmdeps, idents, trees, renderer, options, transf, parseutils,
vmmarshal, gorgeimpl, configuration vmmarshal, gorgeimpl, lineinfos
from semfold import leValueConv, ordinalValToString from semfold import leValueConv, ordinalValToString
from evaltempl import evalTemplate from evaltempl import evalTemplate

View file

@ -10,7 +10,7 @@
## This module contains the type definitions for the new evaluation engine. ## This module contains the type definitions for the new evaluation engine.
## An instruction is 1-3 int32s in memory, it is a register based VM. ## An instruction is 1-3 int32s in memory, it is a register based VM.
import ast, passes, msgs, idents, intsets, options, modulegraphs import ast, passes, msgs, idents, intsets, options, modulegraphs, lineinfos
const const
byteExcess* = 128 # we use excess-K for immediates byteExcess* = 128 # we use excess-K for immediates

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
import ast, types, msgs, os, streams, options, idents import ast, types, msgs, os, streams, options, idents, lineinfos
proc opSlurp*(file: string, info: TLineInfo, module: PSym; conf: ConfigRef): string = proc opSlurp*(file: string, info: TLineInfo, module: PSym; conf: ConfigRef): string =
try: try:

View file

@ -29,7 +29,7 @@
import import
strutils, ast, astalgo, types, msgs, renderer, vmdef, strutils, ast, astalgo, types, msgs, renderer, vmdef,
trees, intsets, rodread, magicsys, options, lowerings trees, intsets, rodread, magicsys, options, lowerings, lineinfos
import platform import platform
from os import splitFile from os import splitFile

View file

@ -10,7 +10,7 @@
## Implements marshaling for the VM. ## Implements marshaling for the VM.
import streams, json, intsets, tables, ast, astalgo, idents, types, msgs, import streams, json, intsets, tables, ast, astalgo, idents, types, msgs,
options options, lineinfos
proc ptrToInt(x: PNode): int {.inline.} = proc ptrToInt(x: PNode): int {.inline.} =
result = cast[int](x) # don't skip alignment result = cast[int](x) # don't skip alignment

View file

@ -15,7 +15,8 @@
## * Computing an aliasing relation based on the assignments. This relation ## * Computing an aliasing relation based on the assignments. This relation
## is then used to compute the 'writes' and 'escapes' effects. ## is then used to compute the 'writes' and 'escapes' effects.
import intsets, idents, ast, astalgo, trees, renderer, msgs, types, options import intsets, idents, ast, astalgo, trees, renderer, msgs, types, options,
lineinfos
const const
debug = false debug = false

View file

@ -17,7 +17,7 @@ import compiler / [options, commands, modules, sem,
passes, passaux, msgs, nimconf, passes, passaux, msgs, nimconf,
extccomp, condsyms, extccomp, condsyms,
sigmatch, ast, scriptconfig, sigmatch, ast, scriptconfig,
idents, modulegraphs, vm, prefixmatches] idents, modulegraphs, vm, prefixmatches, lineinfos]
when defined(windows): when defined(windows):
import winlean import winlean
@ -109,7 +109,7 @@ proc sexp(s: Suggest): SexpNode =
let qp = if s.qualifiedPath.isNil: @[] else: s.qualifiedPath let qp = if s.qualifiedPath.isNil: @[] else: s.qualifiedPath
result = convertSexp([ result = convertSexp([
s.section, s.section,
s.symkind, TSymKind s.symkind,
qp.map(newSString), qp.map(newSString),
s.filePath, s.filePath,
s.forth, s.forth,
@ -141,20 +141,19 @@ proc listEpc(): SexpNode =
methodDesc.add(docstring) methodDesc.add(docstring)
result.add(methodDesc) result.add(methodDesc)
proc findNode(n: PNode): PSym = proc findNode(n: PNode; trackPos: TLineInfo): PSym =
#echo "checking node ", n.info #echo "checking node ", n.info
if n.kind == nkSym: if n.kind == nkSym:
if isTracked(n.info, n.sym.name.s.len): return n.sym if isTracked(n.info, trackPos, n.sym.name.s.len): return n.sym
else: else:
for i in 0 ..< safeLen(n): for i in 0 ..< safeLen(n):
let res = n.sons[i].findNode let res = findNode(n[i], trackPos)
if res != nil: return res if res != nil: return res
proc symFromInfo(graph: ModuleGraph; gTrackPos: TLineInfo): PSym = proc symFromInfo(graph: ModuleGraph; trackPos: TLineInfo): PSym =
let m = graph.getModule(gTrackPos.fileIndex) let m = graph.getModule(trackPos.fileIndex)
#echo m.isNil, " I knew it ", gTrackPos.fileIndex
if m != nil and m.ast != nil: if m != nil and m.ast != nil:
result = m.ast.findNode result = findNode(m.ast, trackPos)
proc execute(cmd: IdeCmd, file, dirtyfile: string, line, col: int; proc execute(cmd: IdeCmd, file, dirtyfile: string, line, col: int;
graph: ModuleGraph; cache: IdentCache) = graph: ModuleGraph; cache: IdentCache) =
@ -163,12 +162,12 @@ proc execute(cmd: IdeCmd, file, dirtyfile: string, line, col: int;
"[" & $line & ":" & $col & "]") "[" & $line & ":" & $col & "]")
conf.ideCmd = cmd conf.ideCmd = cmd
if cmd == ideChk: if cmd == ideChk:
msgs.structuredErrorHook = errorHook conf.structuredErrorHook = errorHook
msgs.writelnHook = myLog conf.writelnHook = myLog
else: else:
msgs.structuredErrorHook = nil conf.structuredErrorHook = nil
msgs.writelnHook = myLog conf.writelnHook = myLog
if cmd == ideUse and suggestVersion != 0: if cmd == ideUse and conf.suggestVersion != 0:
graph.resetAllModules() graph.resetAllModules()
var isKnownFile = true var isKnownFile = true
let dirtyIdx = fileInfoIdx(conf, file, isKnownFile) let dirtyIdx = fileInfoIdx(conf, file, isKnownFile)
@ -176,14 +175,14 @@ proc execute(cmd: IdeCmd, file, dirtyfile: string, line, col: int;
if dirtyfile.len != 0: msgs.setDirtyFile(conf, dirtyIdx, dirtyfile) if dirtyfile.len != 0: msgs.setDirtyFile(conf, dirtyIdx, dirtyfile)
else: msgs.setDirtyFile(conf, dirtyIdx, nil) else: msgs.setDirtyFile(conf, dirtyIdx, nil)
gTrackPos = newLineInfo(dirtyIdx, line, col) conf.m.trackPos = newLineInfo(dirtyIdx, line, col)
gTrackPosAttached = false conf.m.trackPosAttached = false
conf.errorCounter = 0 conf.errorCounter = 0
if suggestVersion == 1: if conf.suggestVersion == 1:
graph.usageSym = nil graph.usageSym = nil
if not isKnownFile: if not isKnownFile:
graph.compileProject(cache) graph.compileProject(cache)
if suggestVersion == 0 and conf.ideCmd in {ideUse, ideDus} and if conf.suggestVersion == 0 and conf.ideCmd in {ideUse, ideDus} and
dirtyfile.len == 0: dirtyfile.len == 0:
discard "no need to recompile anything" discard "no need to recompile anything"
else: else:
@ -193,11 +192,11 @@ proc execute(cmd: IdeCmd, file, dirtyfile: string, line, col: int;
if conf.ideCmd != ideMod: if conf.ideCmd != ideMod:
graph.compileProject(cache, modIdx) graph.compileProject(cache, modIdx)
if conf.ideCmd in {ideUse, ideDus}: if conf.ideCmd in {ideUse, ideDus}:
let u = if suggestVersion != 1: graph.symFromInfo(gTrackPos) else: graph.usageSym let u = if conf.suggestVersion != 1: graph.symFromInfo(conf.m.trackPos) else: graph.usageSym
if u != nil: if u != nil:
listUsages(conf, u) listUsages(conf, u)
else: else:
localError(conf, gTrackPos, "found no symbol at this position " & $gTrackPos) localError(conf, conf.m.trackPos, "found no symbol at this position " & (conf $ conf.m.trackPos))
proc executeEpc(cmd: IdeCmd, args: SexpNode; proc executeEpc(cmd: IdeCmd, args: SexpNode;
graph: ModuleGraph; cache: IdentCache) = graph: ModuleGraph; cache: IdentCache) =
@ -457,16 +456,16 @@ proc mainThread(graph: ModuleGraph; cache: IdentCache) =
else: else:
writelnToChannel(line) writelnToChannel(line)
msgs.writelnHook = wrHook conf.writelnHook = wrHook
suggestionResultHook = sugResultHook conf.suggestionResultHook = sugResultHook
graph.doStopCompile = proc (): bool = requests.peek() > 0 graph.doStopCompile = proc (): bool = requests.peek() > 0
var idle = 0 var idle = 0
var cachedMsgs: CachedMsgs = @[] var cachedMsgs: CachedMsgs = @[]
while true: while true:
let (hasData, req) = requests.tryRecv() let (hasData, req) = requests.tryRecv()
if hasData: if hasData:
msgs.writelnHook = wrHook conf.writelnHook = wrHook
suggestionResultHook = sugResultHook conf.suggestionResultHook = sugResultHook
execCmd(req, graph, cache, cachedMsgs) execCmd(req, graph, cache, cachedMsgs)
idle = 0 idle = 0
else: else:
@ -475,11 +474,11 @@ proc mainThread(graph: ModuleGraph; cache: IdentCache) =
if idle == 20 and gRefresh: if idle == 20 and gRefresh:
# we use some nimsuggest activity to enable a lazy recompile: # we use some nimsuggest activity to enable a lazy recompile:
conf.ideCmd = ideChk conf.ideCmd = ideChk
msgs.writelnHook = proc (s: string) = discard conf.writelnHook = proc (s: string) = discard
cachedMsgs.setLen 0 cachedMsgs.setLen 0
msgs.structuredErrorHook = proc (conf: ConfigRef; info: TLineInfo; msg: string; sev: Severity) = conf.structuredErrorHook = proc (conf: ConfigRef; info: TLineInfo; msg: string; sev: Severity) =
cachedMsgs.add(CachedMsg(info: info, msg: msg, sev: sev)) cachedMsgs.add(CachedMsg(info: info, msg: msg, sev: sev))
suggestionResultHook = proc (s: Suggest) = discard conf.suggestionResultHook = proc (s: Suggest) = discard
recompileFullProject(graph, cache) recompileFullProject(graph, cache)
var var
@ -502,8 +501,8 @@ proc mainCommand(graph: ModuleGraph; cache: IdentCache) =
# do not stop after the first error: # do not stop after the first error:
conf.errorMax = high(int) conf.errorMax = high(int)
# do not print errors, but log them # do not print errors, but log them
msgs.writelnHook = proc (s: string) = log(s) conf.writelnHook = proc (s: string) = log(s)
msgs.structuredErrorHook = nil conf.structuredErrorHook = nil
# compile the project before showing any input so that we already # compile the project before showing any input so that we already
# can answer questions right away: # can answer questions right away:
@ -555,8 +554,8 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; conf: ConfigRef) =
gMode = mepc gMode = mepc
conf.verbosity = 0 # Port number gotta be first. conf.verbosity = 0 # Port number gotta be first.
of "debug": incl(conf.globalOptions, optIdeDebug) of "debug": incl(conf.globalOptions, optIdeDebug)
of "v2": suggestVersion = 0 of "v2": conf.suggestVersion = 0
of "v1": suggestVersion = 1 of "v1": conf.suggestVersion = 1
of "tester": of "tester":
gMode = mstdin gMode = mstdin
gEmitEof = true gEmitEof = true
@ -568,7 +567,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; conf: ConfigRef) =
else: else:
gRefresh = true gRefresh = true
of "maxresults": of "maxresults":
suggestMaxResults = parseInt(p.val) conf.suggestMaxResults = parseInt(p.val)
else: processSwitch(pass, p, conf) else: processSwitch(pass, p, conf)
of cmdArgument: of cmdArgument:
let a = unixToNativePath(p.key) let a = unixToNativePath(p.key)
@ -589,7 +588,7 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
else: else:
processCmdLine(passCmd1, "", conf) processCmdLine(passCmd1, "", conf)
if gMode != mstdin: if gMode != mstdin:
msgs.writelnHook = proc (msg: string) = discard conf.writelnHook = proc (msg: string) = discard
if conf.projectName != "": if conf.projectName != "":
try: try:
conf.projectFull = canonicalizePath(conf, conf.projectName) conf.projectFull = canonicalizePath(conf, conf.projectName)