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
import
msgs, hashes, nversion, options, strutils, std / sha1, ropes, idents,
lineinfos, hashes, nversion, options, strutils, std / sha1, ropes, idents,
intsets, idgen
type

View file

@ -12,7 +12,8 @@
# the data structures here are used in various places of the compiler.
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 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 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):
# these are for debugging only: They are not really deprecated, but I want
# 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
# 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
var h: Hash = hashNode(obj) and high(t.data) # start with real hash value
while t.data[h] != nil:
@ -494,12 +457,12 @@ proc objectSetEnlarge(t: var TObjectSet) =
if t.data[i] != nil: objectSetRawInsert(n, t.data[i])
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)
objectSetRawInsert(t.data, obj)
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:
var h: Hash = hashNode(obj) and high(t.data)
while true:
@ -517,7 +480,7 @@ proc objectSetContainsOrIncl(t: var TObjectSet, obj: RootRef): bool =
inc(t.counter)
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
while t.data[h] != nil:
if (t.data[h] == n):
@ -573,7 +536,7 @@ proc strTableEnlarge(t: var TStrTable) =
if t.data[i] != nil: strTableRawInsert(n, t.data[i])
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)
strTableRawInsert(t.data, n)
inc(t.counter)
@ -609,7 +572,7 @@ proc strTableIncl*(t: var TStrTable, n: PSym; onConflictKeepOld=false): bool {.d
inc(t.counter)
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)
while true:
result = t.data[h]
@ -617,13 +580,13 @@ proc strTableGet(t: TStrTable, name: PIdent): PSym =
if result.name.id == name.id: break
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 start = h
result = tab.data[h]
@ -636,6 +599,12 @@ proc nextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym =
result = tab.data[h]
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,
excluding: IntSet): PSym =
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
else: result = nextIdentExcluding(ti, tab, excluding)
proc initTabIter(ti: var TTabIter, tab: TStrTable): PSym =
ti.h = 0 # we start by zero ...
if tab.counter == 0:
result = nil # FIX 1: removed endless loop
else:
result = nextIter(ti, tab)
type
TTabIter* = object
h: Hash
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
while (ti.h <= high(tab.data)):
result = tab.data[ti.h]
inc(ti.h) # ... and increment by one always
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 =
var it: TTabIter
var s = initTabIter(it, tab)

View file

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

View file

@ -14,12 +14,12 @@ import
nversion, nimsets, msgs, std / sha1, bitsets, idents, types,
ccgutils, os, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
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.`%`
from modulegraphs import ModuleGraph
from configuration import
from lineinfos import
warnGcMem, errXMustBeCompileTime, hintDependency, errGenerated, errCannotOpenFile
import dynlib
@ -949,8 +949,8 @@ proc getFileHeader(conf: ConfigRef; cfile: Cfile): Rope =
proc genFilenames(m: BModule): Rope =
discard cgsym(m, "dbgRegisterFilename")
result = nil
for i in 0..<fileInfos.len:
result.addf("dbgRegisterFilename($1);$N", [fileInfos[i].projPath.makeCString])
for i in 0..<m.config.m.fileInfos.len:
result.addf("dbgRegisterFilename($1);$N", [m.config.m.fileInfos[i].projPath.makeCString])
proc genMainProc(m: BModule) =
const

View file

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

View file

@ -11,7 +11,7 @@
import
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 =
var dest = skipTypes(d, abstractPtrs)

View file

@ -26,7 +26,7 @@ bootSwitch(usedNoGC, defined(nogc), "--gc:none")
import
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.
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)
else: invalidCmdLineOption(conf, pass, orig, info)
if state == wHint:
let x = findStr(configuration.HintsToStr, id)
let x = findStr(lineinfos.HintsToStr, id)
if x >= 0: n = TNoteKind(x + ord(hintMin))
else: localError(conf, info, "unknown hint: " & id)
else:
let x = findStr(configuration.WarningsToStr, id)
let x = findStr(lineinfos.WarningsToStr, id)
if x >= 0: n = TNoteKind(x + ord(warnMin))
else: localError(conf, info, "unknown warning: " & id)
case substr(arg, i).normalize
@ -324,7 +324,7 @@ proc trackDirty(conf: ConfigRef; arg: string, info: TLineInfo) =
if dirtyOriginalIdx.int32 >= 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) =
var a = arg.split(',')
@ -334,7 +334,7 @@ proc track(conf: ConfigRef; arg: string, info: TLineInfo) =
localError(conf, info, errInvalidNumber % a[1])
if parseUtils.parseInt(a[2], column) <= 0:
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) =
if pass in {passCmd2, passPP}:

View file

@ -1,182 +1,6 @@
#
#
# The Nim Compiler
# (c) Copyright 2018 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Use the module 'lineinfos' instead!
## This module contains the rather excessive configuration object that
## needs to be passed around to everything so that the compiler becomes
## more useful as a library.
{.deprecated.}
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"
import lineinfos
export lineinfos

View file

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

View file

@ -23,7 +23,7 @@
## "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
import ast, astalgo, types, intsets, tables, msgs, options
import ast, astalgo, types, intsets, tables, msgs, options, lineinfos
type
InstrKind* = enum

View file

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

View file

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

View file

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

View file

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

View file

@ -9,7 +9,8 @@
## 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) =
result[0] = ""

View file

@ -10,7 +10,7 @@
## This module implements the 'implies' relation for guards.
import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer, idents,
saturate, modulegraphs, options, configuration
saturate, modulegraphs, options, lineinfos
const
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):
assert x.kind in {nkStmtList, nkCall}
# better be safe than sorry, so check evalTemplateCounter too:
inc(evalTemplateCounter)
if evalTemplateCounter > evalTemplateLimit:
inc(c.config.evalTemplateCounter)
if c.config.evalTemplateCounter > evalTemplateLimit:
globalError(c.config, n.info, "template instantiation too nested")
# deactivate this pattern:
c.patterns[i] = nil
@ -54,7 +54,7 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
result = flattenStmts(x)
else:
result = evalPattern(c, x, result)
dec(evalTemplateCounter)
dec(c.config.evalTemplateCounter)
# activate this pattern again:
c.patterns[i] = pattern

View file

@ -11,7 +11,7 @@
import
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 evalFrom*(c: PContext, n: PNode): PNode

View file

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

View file

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

View file

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

View file

@ -11,7 +11,7 @@
import
intsets, strutils, options, ast, astalgo, msgs,
idents, renderer, types, lowerings
idents, renderer, types, lowerings, lineinfos
from pragmas import getPragmaVal
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
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)

View file

@ -12,7 +12,8 @@
const
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
proc newDeref*(n: PNode): PNode {.inline.} =

View file

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

View file

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

View file

@ -25,7 +25,7 @@
## - 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
ModuleGraph* = ref object

View file

@ -7,7 +7,7 @@
# 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

View file

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

View file

@ -9,83 +9,28 @@
import
options, strutils, os, tables, ropes, platform, terminal, macros,
configuration
lineinfos
#type
# 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 =
proc toCChar*(c: char; result: var string) =
case c
of '\0'..'\x1F', '\x7F'..'\xFF': result = '\\' & toOctal(c)
of '\'', '\"', '\\', '?': result = '\\' & c
else: result = $(c)
of '\0'..'\x1F', '\x7F'..'\xFF':
result.add '\\'
result.add toOctal(c)
of '\'', '\"', '\\', '?':
result.add '\\'
result.add c
else:
result.add c
proc makeCString*(s: string): Rope =
const
MaxLineLength = 64
const MaxLineLength = 64
result = nil
var res = newStringOfCap(int(s.len.toFloat * 1.1) + 1)
add(res, "\"")
for i in countup(0, len(s) - 1):
if (i + 1) mod MaxLineLength == 0:
add(res, '\"')
add(res, '\L')
add(res, '\"')
add(res, toCChar(s[i]))
add(res, "\"\L\"")
toCChar(s[i], res)
add(res, '\"')
add(result, rope(res))
@ -110,8 +55,8 @@ proc newFileInfo(fullPath, projPath: string): TFileInfo =
result.fullContent = ""
when defined(nimpretty):
proc fileSection*(fid: FileIndex; a, b: int): string =
substr(fileInfos[fid.int].fullContent, a, b)
proc fileSection*(conf: ConfigRef; fid: FileIndex; a, b: int): string =
substr(conf.m.fileInfos[fid.int].fullContent, a, b)
proc fileInfoKnown*(conf: ConfigRef; filename: string): bool =
var
@ -120,7 +65,7 @@ proc fileInfoKnown*(conf: ConfigRef; filename: string): bool =
canon = canonicalizePath(conf, filename)
except:
canon = filename
result = filenameToIndexTbl.hasKey(canon)
result = conf.m.filenameToIndexTbl.hasKey(canon)
proc fileInfoIdx*(conf: ConfigRef; filename: string; isKnownFile: var bool): FileIndex =
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
pseudoPath = true
if filenameToIndexTbl.hasKey(canon):
result = filenameToIndexTbl[canon]
if conf.m.filenameToIndexTbl.hasKey(canon):
result = conf.m.filenameToIndexTbl[canon]
else:
isKnownFile = false
result = fileInfos.len.FileIndex
fileInfos.add(newFileInfo(canon, if pseudoPath: filename
else: shortenDir(conf, canon)))
filenameToIndexTbl[canon] = result
result = conf.m.fileInfos.len.FileIndex
conf.m.fileInfos.add(newFileInfo(canon, if pseudoPath: filename
else: shortenDir(conf, canon)))
conf.m.filenameToIndexTbl[canon] = result
proc fileInfoIdx*(conf: ConfigRef; filename: string): FileIndex =
var dummy: bool
@ -162,36 +107,19 @@ proc raiseRecoverableError*(msg: string) {.noinline, noreturn.} =
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 =
var totalLen = 0
for s in strings: totalLen += s.len
result = newStringOfCap totalLen
for s in strings: result.add s
proc suggestWriteln*(s: string) =
if eStdOut in errorOutputs:
if isNil(writelnHook):
proc suggestWriteln*(conf: ConfigRef; s: string) =
if eStdOut in conf.m.errorOutputs:
if isNil(conf.writelnHook):
writeLine(stdout, s)
flushFile(stdout)
else:
writelnHook(s)
conf.writelnHook(s)
proc msgQuit*(x: int8) = quit x
proc msgQuit*(x: string) = quit x
@ -212,47 +140,47 @@ const
HintTitle = "Hint: "
HintColor = fgGreen
proc getInfoContextLen*(): int = return msgContext.len
proc setInfoContextLen*(L: int) = setLen(msgContext, L)
proc getInfoContextLen*(conf: ConfigRef): int = return conf.m.msgContext.len
proc setInfoContextLen*(conf: ConfigRef; L: int) = setLen(conf.m.msgContext, L)
proc pushInfoContext*(info: TLineInfo) =
msgContext.add(info)
proc pushInfoContext*(conf: ConfigRef; info: TLineInfo) =
conf.m.msgContext.add(info)
proc popInfoContext*() =
setLen(msgContext, len(msgContext) - 1)
proc popInfoContext*(conf: ConfigRef) =
setLen(conf.m.msgContext, len(conf.m.msgContext) - 1)
proc getInfoContext*(index: int): TLineInfo =
let L = msgContext.len
proc getInfoContext*(conf: ConfigRef; index: int): TLineInfo =
let L = conf.m.msgContext.len
let i = if index < 0: L + index else: index
if i >=% L: result = unknownLineInfo()
else: result = msgContext[i]
else: result = conf.m.msgContext[i]
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 =
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) =
assert fileIdx.int32 >= 0
fileInfos[fileIdx.int32].dirtyFile = filename
conf.m.fileInfos[fileIdx.int32].dirtyFile = filename
proc setHash*(conf: ConfigRef; fileIdx: FileIndex; hash: string) =
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 =
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 =
if fileIdx.int32 < 0:
result = "???"
elif not fileInfos[fileIdx.int32].dirtyFile.isNil:
result = fileInfos[fileIdx.int32].dirtyFile
elif not conf.m.fileInfos[fileIdx.int32].dirtyFile.isNil:
result = conf.m.fileInfos[fileIdx.int32].dirtyFile
else:
result = fileInfos[fileIdx.int32].fullPath
result = conf.m.fileInfos[fileIdx.int32].fullPath
template toFilename*(conf: ConfigRef; info: TLineInfo): string =
toFilename(conf, info.fileIndex)
@ -264,9 +192,9 @@ proc toMsgFilename*(conf: ConfigRef; info: TLineInfo): string =
if info.fileIndex.int32 < 0:
result = "???"
elif optListFullPaths in conf.globalOptions:
result = fileInfos[info.fileIndex.int32].fullPath
result = conf.m.fileInfos[info.fileIndex.int32].fullPath
else:
result = fileInfos[info.fileIndex.int32].projPath
result = conf.m.fileInfos[info.fileIndex.int32].projPath
proc toLinenumber*(info: TLineInfo): int {.inline.} =
result = int info.line
@ -288,12 +216,6 @@ proc `??`* (conf: ConfigRef; info: TLineInfo, filename: string): bool =
# only for debugging purposes
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
MsgFlag* = enum ## flags altering msgWriteln behavior
msgStdout, ## force writing to stdout, even stderr is default
@ -310,14 +232,14 @@ proc msgWriteln*(conf: ConfigRef; s: string, flags: MsgFlags = {}) =
## support.
#if conf.cmd == cmdIdeTools and optCDebug notin gGlobalOptions: return
if not isNil(writelnHook) and msgSkipHook notin flags:
writelnHook(s)
if not isNil(conf.writelnHook) and msgSkipHook notin flags:
conf.writelnHook(s)
elif optStdout in conf.globalOptions or msgStdout in flags:
if eStdOut in errorOutputs:
if eStdOut in conf.m.errorOutputs:
writeLine(stdout, s)
flushFile(stdout)
else:
if eStdErr in errorOutputs:
if eStdErr in conf.m.errorOutputs:
writeLine(stderr, s)
# On Windows stderr is fully-buffered when piped, regardless of C std.
when defined(windows):
@ -348,17 +270,17 @@ macro callStyledWriteLineStderr(args: varargs[typed]): untyped =
result.add(arg)
template callWritelnHook(args: varargs[string, `$`]) =
writelnHook concat(args)
conf.writelnHook concat(args)
template styledMsgWriteln*(args: varargs[typed]) =
if not isNil(writelnHook):
if not isNil(conf.writelnHook):
callIgnoringStyle(callWritelnHook, nil, args)
elif optStdout in conf.globalOptions:
if eStdOut in errorOutputs:
if eStdOut in conf.m.errorOutputs:
callIgnoringStyle(writeLine, stdout, args)
flushFile(stdout)
else:
if eStdErr in errorOutputs:
if eStdErr in conf.m.errorOutputs:
if optUseColors in conf.globalOptions:
callStyledWriteLineStderr(args)
else:
@ -389,7 +311,7 @@ proc log*(s: string) {.procvar.} =
proc quit(conf: ConfigRef; msg: TMsgKind) =
if defined(debug) or msg == errInternal or hintStackTrace in conf.notes:
if stackTraceAvailable() and isNil(writelnHook):
if stackTraceAvailable() and isNil(conf.writelnHook):
writeStackTrace()
else:
styledMsgWriteln(fgRed, "No stack traceback available\n" &
@ -420,19 +342,19 @@ proc exactEquals*(a, b: TLineInfo): bool =
proc writeContext(conf: ConfigRef; lastinfo: TLineInfo) =
const instantiationFrom = "template/generic instantiation from here"
var info = lastinfo
for i in countup(0, len(msgContext) - 1):
if msgContext[i] != lastinfo and msgContext[i] != info:
if structuredErrorHook != nil:
structuredErrorHook(conf, msgContext[i], instantiationFrom,
Severity.Error)
for i in 0 ..< len(conf.m.msgContext):
if conf.m.msgContext[i] != lastinfo and conf.m.msgContext[i] != info:
if conf.structuredErrorHook != nil:
conf.structuredErrorHook(conf, conf.m.msgContext[i], instantiationFrom,
Severity.Error)
else:
styledMsgWriteln(styleBright,
PosFormat % [toMsgFilename(conf, msgContext[i]),
coordToStr(msgContext[i].line.int),
coordToStr(msgContext[i].col+1)],
PosFormat % [toMsgFilename(conf, conf.m.msgContext[i]),
coordToStr(conf.m.msgContext[i].line.int),
coordToStr(conf.m.msgContext[i].col+1)],
resetStyle,
instantiationFrom)
info = msgContext[i]
info = conf.m.msgContext[i]
proc ignoreMsgBecauseOfIdeTools(conf: ConfigRef; msg: TMsgKind): bool =
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)
let s = msgKindToString(msg) % args
if structuredErrorHook != nil:
structuredErrorHook(conf, unknownLineInfo(), s & (if kind != nil: KindFormat % kind else: ""), sev)
if conf.structuredErrorHook != nil:
conf.structuredErrorHook(conf, unknownLineInfo(),
s & (if kind != nil: KindFormat % kind else: ""), sev)
if not ignoreMsgBecauseOfIdeTools(conf, msg):
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
# in the same file and line are produced:
#ignoreMsg = lastError == info and eh != doAbort
lastError = info
conf.m.lastError = info
of warnMin..warnMax:
sev = Severity.Warning
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)
if not ignoreMsg:
if structuredErrorHook != nil:
structuredErrorHook(conf, info, s & (if kind != nil: KindFormat % kind else: ""), sev)
if conf.structuredErrorHook != nil:
conf.structuredErrorHook(conf, info, s & (if kind != nil: KindFormat % kind else: ""), sev)
if not ignoreMsgBecauseOfIdeTools(conf, msg):
if kind != nil:
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 = "") =
# this fixes bug #7080 so that it is at least obvious 'fatal'
# was executed.
errorOutputs = {eStdOut, eStdErr}
conf.m.errorOutputs = {eStdOut, eStdErr}
liMessage(conf, info, msg, arg, doAbort)
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)
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)
liMessage(conf, info, errInternal, errMsg, doAbort)
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())
rawMessage(conf, errInternal, errMsg)
@ -596,36 +519,36 @@ template internalAssert*(conf: ConfigRef, e: bool) =
if not e: internalError(conf, $instantiationInfo())
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 =
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:
for line in lines(toFullPath(conf, i)):
addSourceLine conf, i.fileIndex, line.string
except IOError:
discard
assert i.fileIndex.int32 < fileInfos.len
assert i.fileIndex.int32 < conf.m.fileInfos.len
# 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 =
assert i.fileIndex.int32 >= 0
if optExcessiveStackTrace in conf.globalOptions:
result = fileInfos[i.fileIndex.int32].quotedFullName
result = conf.m.fileInfos[i.fileIndex.int32].quotedFullName
else:
result = fileInfos[i.fileIndex.int32].quotedName
result = conf.m.fileInfos[i.fileIndex.int32].quotedName
proc listWarnings*(conf: ConfigRef) =
msgWriteln(conf, "Warnings:")
for warn in warnMin..warnMax:
msgWriteln(conf, " [$1] $2" % [
if warn in conf.notes: "x" else: " ",
configuration.WarningsToStr[ord(warn) - ord(warnMin)]
lineinfos.WarningsToStr[ord(warn) - ord(warnMin)]
])
proc listHints*(conf: ConfigRef) =
@ -633,5 +556,5 @@ proc listHints*(conf: ConfigRef) =
for hint in hintMin..hintMax:
msgWriteln(conf, " [$1] $2" % [
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
commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
extccomp, strutils, os, osproc, platform, main, parseopt, service,
nodejs, scriptconfig, idents, modulegraphs, configuration
nodejs, scriptconfig, idents, modulegraphs, lineinfos
when hasTinyCBackend:
import tccgen

View file

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

View file

@ -11,7 +11,7 @@
import
llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer,
options, idents, wordrecg, strtabs, configuration
options, idents, wordrecg, strtabs, lineinfos
# ---------------- configuration file parser -----------------------------
# we use Nim's scanner here to save space and work

View file

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

View file

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

View file

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

View file

@ -15,6 +15,6 @@ const
VersionAsString* = system.NimVersion
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
## declare this.

View file

@ -8,7 +8,8 @@
#
import
os, strutils, strtabs, osproc, sets, configuration, platform
os, strutils, strtabs, osproc, sets, lineinfos, platform,
prefixmatches
from terminal import isatty
@ -135,11 +136,33 @@ type
flags*: set[CFileFlag]
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
target*: Target
linesCompiled*: int # all lines that have been compiled
options*: TOptions
globalOptions*: TGlobalOptions
m*: MsgConfig
evalTemplateCounter*: int
exitcode*: int8
cmd*: TCommands # the command
selectedGC*: TGCMode # the selected GC
@ -202,6 +225,13 @@ type
compileOptions*: string
ccompilerpath*: string
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}
@ -229,6 +259,7 @@ proc newConfigRef*(): ConfigRef =
verbosity: 1,
options: DefaultOptions,
globalOptions: DefaultGlobalOptions,
m: initMsgConfig(),
evalExpr: "",
cppDefines: initSet[string](),
headerFile: "", features: {}, foreignPackageNotes: {hintProcessing, warnUnknownMagic,
@ -264,7 +295,8 @@ proc newConfigRef*(): ConfigRef =
compileOptions: "",
ccompilerpath: "",
toCompile: @[],
arguments: ""
arguments: "",
suggestMaxResults: 10_000
)
setTargetFromSystem(result.target)
# enable colors by default on terminals

View file

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

View file

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

View file

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

View file

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

View file

@ -24,7 +24,7 @@ proc prefixMatch*(p, s: string): PrefixMatch =
# check for prefix/contains:
while i < L:
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 jj = 1
while ii < L and jj < p.len:
@ -43,10 +43,10 @@ proc prefixMatch*(p, s: string): PrefixMatch =
i = 1
var j = 1
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
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
else: return PrefixMatch.None
inc i

View file

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

View file

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

View file

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

View file

@ -91,7 +91,7 @@
import
os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms,
ropes, idents, std / sha1, idgen, types, rodutils, memfiles, tables,
configuration
lineinfos
type
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
# be used twice! However, compilation speed does not suffer much from
# this, since results are cached.
var res = checkDep(systemFileIdx, cache, conf)
var res = checkDep(conf.m.systemFileIdx, cache, conf)
if res != rrNone: result = rrModDeps
for i in countup(0, high(r.modDeps)):
res = checkDep(r.modDeps[i], cache, conf)

View file

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

View file

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

View file

@ -13,7 +13,7 @@
import
ast, modules, idents, passes, passaux, condsyms,
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:
from strutils import cmpIgnoreStyle, contains

View file

@ -16,7 +16,7 @@ import
procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch,
intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
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
@ -52,10 +52,10 @@ proc isArrayConstr(n: PNode): bool {.inline.} =
result = n.kind == nkBracket and
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
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
template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
@ -307,9 +307,9 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
let oldErrorCount = c.config.errorCounter
let oldErrorMax = c.config.errorMax
let oldErrorOutputs = errorOutputs
let oldErrorOutputs = c.config.m.errorOutputs
errorOutputs = {}
c.config.m.errorOutputs = {}
c.config.errorMax = high(int)
try:
@ -324,7 +324,7 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
c.config.errorCounter = oldErrorCount
c.config.errorMax = oldErrorMax
errorOutputs = oldErrorOutputs
c.config.m.errorOutputs = oldErrorOutputs
const
errConstExprExpected = "constant expression expected"
@ -340,9 +340,9 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
result = evalConstExpr(c.module, c.cache, c.graph, e)
if result == nil or result.kind == nkEmpty:
if e.info != n.info:
pushInfoContext(n.info)
pushInfoContext(c.config, n.info)
localError(c.config, e.info, errConstExprExpected)
popInfoContext()
popInfoContext(c.config)
else:
localError(c.config, e.info, errConstExprExpected)
# error correction:
@ -380,8 +380,8 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
## coherence, making sure that variables declared with 'let' aren't
## reassigned, and binding the unbound identifiers that the macro output
## contains.
inc(evalTemplateCounter)
if evalTemplateCounter > evalTemplateLimit:
inc(c.config.evalTemplateCounter)
if c.config.evalTemplateCounter > evalTemplateLimit:
globalError(c.config, s.info, "template instantiation too nested")
c.friendModules.add(s.owner.getModule)
@ -420,8 +420,8 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
result = semExpr(c, result, flags)
result = fitNode(c, retType, result, result.info)
#GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
dec(evalTemplateCounter)
#globalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
dec(c.config.evalTemplateCounter)
discard c.friendModules.pop()
const
@ -429,7 +429,7 @@ const
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
flags: TExprFlags = {}): PNode =
pushInfoContext(nOrig.info)
pushInfoContext(c.config, nOrig.info)
markUsed(c.config, n.info, sym, c.graph.usageSym)
styleCheckUse(n.info, sym)
@ -449,7 +449,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
if efNoSemCheck notin flags:
result = semAfterMacroCall(c, n, result, sym, flags)
result = wrapInComesFrom(nOrig.info, sym, result)
popInfoContext()
popInfoContext(c.config)
proc forceBool(c: PContext, n: PNode): PNode =
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:
result = semStmtAndGenerateGenerics(c, n)
else:
let oldContextLen = msgs.getInfoContextLen()
let oldContextLen = msgs.getInfoContextLen(c.config)
let oldInGenericInst = c.inGenericInst
try:
result = semStmtAndGenerateGenerics(c, n)
except ERecoverableError, ESuggestDone:
recoverContext(c)
c.inGenericInst = oldInGenericInst
msgs.setInfoContextLen(oldContextLen)
msgs.setInfoContextLen(c.config, oldContextLen)
if getCurrentException() of ESuggestDone:
c.suggestionsMade = true
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,
# as semOverlodedCall is already pretty slow (and we need this information
# only in case of an error).
if errorOutputs == {}:
if c.config.m.errorOutputs == {}:
# fail fast:
globalError(c.config, n.info, "type mismatch")
if errors.len == 0:
@ -332,7 +332,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
internalAssert c.config, result.state == csMatch
#writeMatches(result)
#writeMatches(alt)
if errorOutputs == {}:
if c.config.m.errorOutputs == {}:
# quick error message for performance of 'compiles' built-in:
globalError(c.config, n.info, errGenerated, "ambiguous call")
elif c.config.errorCounter == 0:

View file

@ -14,7 +14,7 @@ import
wordrecg,
ropes, msgs, platform, os, condsyms, idents, renderer, types, extccomp, math,
magicsys, nversion, nimsets, parser, times, passes, rodread, vmdef,
modulegraphs, configuration
modulegraphs, lineinfos
type
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 =
markUsed(c.config, n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s)
pushInfoContext(n.info)
pushInfoContext(c.config, n.info)
result = evalTemplate(n, s, getCurrOwner(c), c.config, efFromHlo in 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
@ -742,7 +742,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
# This is a proc variable, apply normal overload resolution
let m = resolveIndirectCall(c, n, nOrig, t)
if m.state != csMatch:
if errorOutputs == {}:
if c.config.m.errorOutputs == {}:
# speed up error generation:
globalError(c.config, n.info, "type mismatch")
return c.graph.emptyNode
@ -1082,7 +1082,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
when defined(nimsuggest):
if c.config.cmd == cmdIdeTools:
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})
if s != nil:
@ -1783,9 +1783,9 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
openScope(c)
let oldOwnerLen = len(c.graph.owners)
let oldGenerics = c.generics
let oldErrorOutputs = errorOutputs
if efExplain notin flags: errorOutputs = {}
let oldContextLen = msgs.getInfoContextLen()
let oldErrorOutputs = c.config.m.errorOutputs
if efExplain notin flags: c.config.m.errorOutputs = {}
let oldContextLen = msgs.getInfoContextLen(c.config)
let oldInGenericContext = c.inGenericContext
let oldInUnrolledContext = c.inUnrolledContext
@ -1807,10 +1807,10 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
c.inGenericInst = oldInGenericInst
c.inStaticContext = oldInStaticContext
c.p = oldProcCon
msgs.setInfoContextLen(oldContextLen)
msgs.setInfoContextLen(c.config, oldContextLen)
setLen(c.graph.owners, oldOwnerLen)
c.currentScope = oldScope
errorOutputs = oldErrorOutputs
c.config.m.errorOutputs = oldErrorOutputs
c.config.errorCounter = oldErrorCount
c.config.errorMax = oldErrorMax
@ -2309,7 +2309,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# check if it is an expression macro:
checkMinSonsLen(n, 1, c.config)
#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}
var s = qualifiedLookUp(c, n.sons[0], mode)
if s != nil:

View file

@ -13,7 +13,7 @@
import
strutils, options, ast, astalgo, trees, treetab, nimsets, times,
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 =
case skipTypes(n.typ, abstractVarRange).kind

View file

@ -55,7 +55,7 @@ template macroToExpandSym(s): untyped =
proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
ctx: var GenericCtx; fromDotExpr=false): PNode =
semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody)
semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
incl(s.flags, sfUsed)
case s.kind
of skUnknown:
@ -129,7 +129,7 @@ proc newDot(n, b: PNode): PNode =
proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
ctx: var GenericCtx; isMacro: var bool): PNode =
assert n.kind == nkDotExpr
semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody)
semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
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 conf.cmd == cmdIdeTools: suggestStmt(c, n)
semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody)
semIdeForTemplateOrGenericCheck(c.config, n, ctx.cursorInBody)
case n.kind
of nkIdent, nkAccQuoted:

View file

@ -159,13 +159,13 @@ proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
var oldPrc = c.generics[i].inst.sym
pushProcCon(c, oldPrc)
pushOwner(c, oldPrc)
pushInfoContext(oldPrc.info)
pushInfoContext(c.config, oldPrc.info)
openScope(c)
var n = oldPrc.ast
n.sons[bodyPos] = copyTree(s.getBody)
instantiateBody(c, n, oldPrc.typ.n, oldPrc, s)
closeScope(c)
popInfoContext()
popInfoContext(c.config)
popOwner(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
# will need to use openScope, addDecl, etc.
#addDecl(c, prc)
pushInfoContext(info)
pushInfoContext(c.config, info)
var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(c, addr(typeMap), info, nil)
var result = instCopyType(cl, prc.typ)
@ -278,7 +278,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
skipIntLiteralParams(result)
prc.typ = result
popInfoContext()
popInfoContext(c.config)
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
info: TLineInfo): PSym =
@ -309,7 +309,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
let gp = n.sons[genericParamsPos]
internalAssert c.config, gp.kind != nkEmpty
n.sons[namePos] = newSymNode(result)
pushInfoContext(info)
pushInfoContext(c.config, info)
var entry = TInstantiation.new
entry.sym = result
# 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:
result = oldPrc
popProcCon(c)
popInfoContext()
popInfoContext(c.config)
closeScope(c) # close scope for parameters
popOwner(c)
c.currentScope = oldScope

View file

@ -76,7 +76,7 @@ proc semInstantiationInfo(c: PContext, n: PNode): PNode =
result = newNodeIT(nkTupleConstr, n.info, n.typ)
let idx = expectIntLit(c, n.sons[1])
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))
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))

View file

@ -9,7 +9,7 @@
import
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
wordrecg, strutils, options, guards, writetracking, configuration,
wordrecg, strutils, options, guards, writetracking, lineinfos,
modulegraphs
when defined(useDfa):
@ -859,9 +859,9 @@ proc checkRaisesSpec(g: ModuleGraph; spec, real: PNode, msg: string, hints: bool
used.incl(s)
break search
# 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))
popInfoContext()
popInfoContext(g.config)
# hint about unnecessarily listed exception types:
if hints:
for s in 0 ..< spec.len:

View file

@ -89,7 +89,7 @@ proc semWhile(c: PContext, n: PNode): PNode =
result.typ = c.enforceVoidContext
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):
result = sonsLen(t2.n)
else:
@ -201,7 +201,7 @@ proc semCase(c: PContext, n: PNode): PNode =
for i in countup(1, sonsLen(n) - 1):
var x = n.sons[i]
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)
case x.kind
of nkOfBranch:
@ -1396,14 +1396,14 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
localError(c.config, n.info, errGenerated,
"'destroy' or 'deepCopy' expected for 'override'")
proc cursorInProcAux(n: PNode): bool =
if inCheckpoint(n.info) != cpNone: return true
proc cursorInProcAux(conf: ConfigRef; n: PNode): bool =
if inCheckpoint(n.info, conf.m.trackPos) != cpNone: return true
for i in 0..<n.safeLen:
if cursorInProcAux(n[i]): return true
if cursorInProcAux(conf, n[i]): return true
proc cursorInProc(n: PNode): bool =
if n.info.fileIndex == gTrackPos.fileIndex:
result = cursorInProcAux(n)
proc cursorInProc(conf: ConfigRef; n: PNode): bool =
if n.info.fileIndex == conf.m.trackPos.fileIndex:
result = cursorInProcAux(conf, n)
type
TProcCompilationSteps = enum
@ -1583,7 +1583,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
# only used for overload resolution (there is no instantiation of
# the symbol, so we must process the body now)
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"
if s.kind == skMethod: semMethodPrototype(c, s, n)
else:

View file

@ -305,7 +305,7 @@ proc semTemplBodySons(c: var TemplCtx, n: PNode): PNode =
proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
result = n
semIdeForTemplateOrGenericCheck(n, c.cursorInBody)
semIdeForTemplateOrGenericCheck(c.c.config, n, c.cursorInBody)
case n.kind
of nkIdent:
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 =
result = n
semIdeForTemplateOrGenericCheck(n, c.cursorInBody)
semIdeForTemplateOrGenericCheck(c.c.config, n, c.cursorInBody)
case n.kind
of nkIdent:
let s = qualifiedLookUp(c.c, n, {})

View file

@ -9,7 +9,8 @@
# 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
tfInstClearedFlags = {tfHasMeta, tfUnresolved}
@ -568,35 +569,35 @@ proc replaceTypesInBody*(p: PContext, pt: TIdTable, n: PNode;
var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(p, addr(typeMap), n.info, owner)
cl.allowMetaTypes = allowMetaTypes
pushInfoContext(n.info)
pushInfoContext(p.config, n.info)
result = replaceTypeVarsN(cl, n)
popInfoContext()
popInfoContext(p.config)
proc replaceTypesForLambda*(p: PContext, pt: TIdTable, n: PNode;
original, new: PSym): PNode =
var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(p, addr(typeMap), n.info, original)
idTablePut(cl.symMap, original, new)
pushInfoContext(n.info)
pushInfoContext(p.config, n.info)
result = replaceTypeVarsN(cl, n)
popInfoContext()
popInfoContext(p.config)
proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo,
t: PType): PType =
var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(p, addr(typeMap), info, nil)
pushInfoContext(info)
pushInfoContext(p.config, info)
result = replaceTypeVarsT(cl, t)
popInfoContext()
popInfoContext(p.config)
proc prepareMetatypeForSigmatch*(p: PContext, pt: TIdTable, info: TLineInfo,
t: PType): PType =
var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(p, addr(typeMap), info, nil)
cl.allowMetaTypes = true
pushInfoContext(info)
pushInfoContext(p.config, info)
result = replaceTypeVarsT(cl, t)
popInfoContext()
popInfoContext(p.config)
template generateTypeInstance*(p: PContext, pt: TIdTable, arg: PNode,
t: PType): untyped =

View file

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

View file

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

View file

@ -32,7 +32,7 @@
# included from sigmatch.nim
import algorithm, prefixmatches, configuration
import algorithm, prefixmatches, lineinfos
from wordrecg import wDeprecated
when defined(nimsuggest):
@ -41,31 +41,6 @@ when defined(nimsuggest):
const
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 origModuleName(m: PSym): string = m.name.s
@ -104,7 +79,7 @@ proc cmpSuggestions(a, b: Suggest): int =
cf globalUsages
# if all is equal, sort alphabetically for deterministic output,
# 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;
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.contextFits = inTypeContext == (s.kind in {skType, skGenericParam})
result.scope = scope
result.name = s.name
result.name = addr s.name.s
when defined(nimsuggest):
result.globalUsages = s.allUsages.len
var c = 0
for u in s.allUsages:
if u.fileIndex == info.fileIndex: inc c
result.localUsages = c
result.symkind = s.kind
result.symkind = byte s.kind
if optIdeTerse notin conf.globalOptions:
result.qualifiedPath = @[]
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.line = toLinenumber(infox)
result.column = toColumn(infox)
result.version = conf.suggestVersion
proc `$`*(suggest: Suggest): string =
result = $suggest.section
result.add(sep)
if suggest.section == ideHighlight:
if suggest.symkind == skVar and suggest.isGlobal:
if suggest.symkind.TSymKind == skVar and suggest.isGlobal:
result.add("skGlobalVar")
elif suggest.symkind == skLet and suggest.isGlobal:
elif suggest.symkind.TSymKind == skLet and suggest.isGlobal:
result.add("skGlobalLet")
else:
result.add($suggest.symkind)
result.add($suggest.symkind.TSymKind)
result.add(sep)
result.add($suggest.line)
result.add(sep)
@ -164,9 +140,9 @@ proc `$`*(suggest: Suggest): string =
result.add(sep)
result.add($suggest.tokenLen)
else:
result.add($suggest.symkind)
result.add($suggest.symkind.TSymKind)
result.add(sep)
if suggest.qualifiedPath != nil:
if suggest.qualifiedPath.len != 0:
result.add(suggest.qualifiedPath.join("."))
result.add(sep)
result.add(suggest.forth)
@ -179,18 +155,18 @@ proc `$`*(suggest: Suggest): string =
result.add(sep)
when not defined(noDocgen):
result.add(suggest.doc.escape)
if suggestVersion == 0:
if suggest.version == 0:
result.add(sep)
result.add($suggest.quality)
if suggest.section == ideSug:
result.add(sep)
result.add($suggest.prefix)
proc suggestResult(s: Suggest) =
if not isNil(suggestionResultHook):
suggestionResultHook(s)
proc suggestResult(conf: ConfigRef; s: Suggest) =
if not isNil(conf.suggestionResultHook):
conf.suggestionResultHook(s)
else:
suggestWriteln($s)
conf.suggestWriteln($s)
proc produceOutput(a: var Suggestions; conf: ConfigRef) =
if conf.ideCmd in {ideSug, ideCon}:
@ -198,13 +174,13 @@ proc produceOutput(a: var Suggestions; conf: ConfigRef) =
when defined(debug):
# debug code
writeStackTrace()
if a.len > suggestMaxResults: a.setLen(suggestMaxResults)
if not isNil(suggestionResultHook):
if a.len > conf.suggestMaxResults: a.setLen(conf.suggestMaxResults)
if not isNil(conf.suggestionResultHook):
for s in a:
suggestionResultHook(s)
conf.suggestionResultHook(s)
else:
for s in a:
suggestWriteln($s)
conf.suggestWriteln($s)
proc filterSym(s: PSym; prefix: PNode; res: var PrefixMatch): bool {.inline.} =
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 pm: PrefixMatch
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.
let fullPath = findModule(c.config, n.sym.name.s, toFullPath(c.config, n.info))
if fullPath.len == 0:
@ -397,17 +373,17 @@ type
TCheckPointResult* = enum
cpNone, cpFuzzy, cpExact
proc inCheckpoint*(current: TLineInfo): TCheckPointResult =
if current.fileIndex == gTrackPos.fileIndex:
if current.line == gTrackPos.line and
abs(current.col-gTrackPos.col) < 4:
proc inCheckpoint*(current, trackPos: TLineInfo): TCheckPointResult =
if current.fileIndex == trackPos.fileIndex:
if current.line == trackPos.line and
abs(current.col-trackPos.col) < 4:
return cpExact
if current.line >= gTrackPos.line:
if current.line >= trackPos.line:
return cpFuzzy
proc isTracked*(current: TLineInfo, tokenLen: int): bool =
if current.fileIndex==gTrackPos.fileIndex and current.line==gTrackPos.line:
let col = gTrackPos.col
proc isTracked*(current, trackPos: TLineInfo, tokenLen: int): bool =
if current.fileIndex==trackPos.fileIndex and current.line==trackPos.line:
let col = trackPos.col
if col >= current.col and col <= current.col+tokenLen-1:
return true
@ -425,30 +401,27 @@ when defined(nimsuggest):
if infoB.infoToInt == infoAsInt: return
s.allUsages.add(info)
var
lastLineInfo*: TLineInfo # XXX global here
proc findUsages(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) =
if suggestVersion == 1:
if usageSym == nil and isTracked(info, s.name.s.len):
if conf.suggestVersion == 1:
if usageSym == nil and isTracked(info, conf.m.trackPos, s.name.s.len):
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:
if lastLineInfo != info:
suggestResult(symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0))
lastLineInfo = info
if conf.lastLineInfo != info:
suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0))
conf.lastLineInfo = info
when defined(nimsuggest):
proc listUsages*(conf: ConfigRef; s: PSym) =
#echo "usages ", len(s.allUsages)
for info in s.allUsages:
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) =
if s.isNil: return
if isTracked(info, s.name.s.len):
suggestResult(symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0))
if isTracked(info, conf.m.trackPos, s.name.s.len):
suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0))
suggestQuit()
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.} =
## misnamed: should be 'symDeclared'
when defined(nimsuggest):
if suggestVersion == 0:
if conf.suggestVersion == 0:
if s.allUsages.isNil:
s.allUsages = @[info]
else:
@ -471,14 +444,14 @@ proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym;
elif conf.ideCmd == ideDef:
findDefinition(conf, info, s)
elif conf.ideCmd == ideDus and s != nil:
if isTracked(info, s.name.s.len):
suggestResult(symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0))
if isTracked(info, conf.m.trackPos, s.name.s.len):
suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0))
findUsages(conf, info, s, usageSym)
elif conf.ideCmd == ideHighlight and info.fileIndex == gTrackPos.fileIndex:
suggestResult(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 == ideHighlight and info.fileIndex == conf.m.trackPos.fileIndex:
suggestResult(conf, symToSuggest(conf, s, isLocal=false, ideHighlight, info, 100, PrefixMatch.None, false, 0))
elif conf.ideCmd == ideOutline and info.fileIndex == conf.m.trackPos.fileIndex and
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) =
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
# 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
not gTrackPosAttached: n[1] else: nil
not c.config.m.trackPosAttached: n[1] else: nil
suggestFieldAccess(c, obj, prefix, outputs)
#if optIdeDebug in gGlobalOptions:
# echo "expression ", renderTree(obj), " has type ", typeToString(obj.typ)
#writeStackTrace()
else:
let prefix = if gTrackPosAttached: nil else: n
let prefix = if c.config.m.trackPosAttached: nil else: n
suggestEverything(c, n, prefix, outputs)
proc suggestExprNoCheck*(c: PContext, n: PNode) =
@ -555,10 +528,10 @@ proc suggestExprNoCheck*(c: PContext, n: PNode) =
suggestQuit()
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) =
let attached = gTrackPosAttached
let attached = c.config.m.trackPosAttached
if attached: inc(c.inTypeContext)
defer:
if attached: dec(c.inTypeContext)
@ -574,7 +547,7 @@ proc suggestEnum*(c: PContext; n: PNode; t: PType) =
if outputs.len > 0: suggestQuit()
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
inc(c.compilesContextId)
var outputs: Suggestions = @[]
@ -587,7 +560,9 @@ proc suggestSentinel*(c: PContext) =
for it in items(scope.symbols):
var pm: PrefixMatch
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)
produceOutput(outputs, c.config)

View file

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

View file

@ -22,7 +22,7 @@ import
intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os,
idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread,
lambdalifting, sempass2, lowerings, lookups, destroyer, liftlocals,
modulegraphs
modulegraphs, lineinfos
type
PTransNode* = distinct PNode
@ -598,7 +598,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
idNodeTablePut(newC.mapping, formal, temp)
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:
var symMap: TIdTable
initIdTable symMap
@ -608,7 +608,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
add(stmtList, transform(c, body))
#findWrongOwners(c, stmtList.pnode)
dec(c.inlining)
popInfoContext()
popInfoContext(c.graph.config)
popTransCon(c)
# echo "transformed: ", stmtList.PNode.renderTree

View file

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

View file

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

View file

@ -10,7 +10,7 @@
## 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.
import ast, passes, msgs, idents, intsets, options, modulegraphs
import ast, passes, msgs, idents, intsets, options, modulegraphs, lineinfos
const
byteExcess* = 128 # we use excess-K for immediates

View file

@ -7,7 +7,7 @@
# 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 =
try:

View file

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

View file

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

View file

@ -15,7 +15,8 @@
## * Computing an aliasing relation based on the assignments. This relation
## 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
debug = false

View file

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