Merge branch 'master' of github.com:Araq/Nimrod

This commit is contained in:
Araq 2011-12-12 01:40:47 +01:00
commit 98ed7fbf16
24 changed files with 223 additions and 146 deletions

View file

@ -97,7 +97,7 @@ type
next*: ref TToken # for C we need arbitrary look-ahead :-( next*: ref TToken # for C we need arbitrary look-ahead :-(
TLexer* = object of TBaseLexer TLexer* = object of TBaseLexer
filename*: string fileIdx*: int32
inDirective: bool inDirective: bool
proc getTok*(L: var TLexer, tok: var TToken) proc getTok*(L: var TLexer, tok: var TToken)
@ -117,7 +117,7 @@ proc fillToken(L: var TToken) =
proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream) = proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream) =
openBaseLexer(lex, inputstream) openBaseLexer(lex, inputstream)
lex.filename = filename lex.fileIdx = filename.fileInfoIdx
proc closeLexer*(lex: var TLexer) = proc closeLexer*(lex: var TLexer) =
inc(gLinesCompiled, lex.LineNumber) inc(gLinesCompiled, lex.LineNumber)
@ -127,13 +127,13 @@ proc getColumn*(L: TLexer): int =
result = getColNumber(L, L.bufPos) result = getColNumber(L, L.bufPos)
proc getLineInfo*(L: TLexer): TLineInfo = proc getLineInfo*(L: TLexer): TLineInfo =
result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos)) result = newLineInfo(L.fileIdx, L.linenumber, getColNumber(L, L.bufpos))
proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") = proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") =
msgs.GenericMessage(getLineInfo(L), msg, arg) msgs.GenericMessage(getLineInfo(L), msg, arg)
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart) var info = newLineInfo(L.fileIdx, L.linenumber, pos - L.lineStart)
msgs.GenericMessage(info, msg, arg) msgs.GenericMessage(info, msg, arg)
proc TokKindToStr*(k: TTokKind): string = proc TokKindToStr*(k: TTokKind): string =

View file

@ -460,8 +460,6 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
else: InvalidCmdLineOption(pass, switch, info) else: InvalidCmdLineOption(pass, switch, info)
proc ProcessCommand(switch: string, pass: TCmdLinePass) = proc ProcessCommand(switch: string, pass: TCmdLinePass) =
var var cmd, arg: string
cmd, arg: string splitSwitch(switch, cmd, arg, pass, gCmdLineInfo)
var info = newLineInfo("command line", 1, 1) processSwitch(cmd, arg, pass, gCmdLineInfo)
splitSwitch(switch, cmd, arg, pass, info)
ProcessSwitch(cmd, arg, pass, info)

View file

@ -33,10 +33,10 @@ proc addDotDependency(c: PPassContext, n: PNode): PNode =
case n.kind case n.kind
of nkImportStmt: of nkImportStmt:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var imported = splitFile(getModuleFile(n.sons[i])).name var imported = getModuleName(n.sons[i])
addDependencyAux(g.module.name.s, imported) addDependencyAux(g.module.name.s, imported)
of nkFromStmt: of nkFromStmt:
var imported = splitFile(getModuleFile(n.sons[0])).name var imported = getModuleName(n.sons[0])
addDependencyAux(g.module.name.s, imported) addDependencyAux(g.module.name.s, imported)
of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr: of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr:
for i in countup(0, sonsLen(n) - 1): discard addDotDependency(c, n.sons[i]) for i in countup(0, sonsLen(n) - 1): discard addDotDependency(c, n.sons[i])

View file

@ -13,7 +13,7 @@
import import
ast, astalgo, strutils, hashes, options, nversion, msgs, os, ropes, idents, ast, astalgo, strutils, hashes, options, nversion, msgs, os, ropes, idents,
wordrecg, math, syntaxes, renderer, lexer, rst, times, highlite wordrecg, math, syntaxes, renderer, lexer, rst, times, highlite, importer
proc CommandDoc*() proc CommandDoc*()
proc CommandRst2Html*() proc CommandRst2Html*()
@ -760,21 +760,12 @@ proc renderRstToOut(d: PDoc, n: PRstNode): PRope =
proc checkForFalse(n: PNode): bool = proc checkForFalse(n: PNode): bool =
result = n.kind == nkIdent and IdentEq(n.ident, "false") result = n.kind == nkIdent and IdentEq(n.ident, "false")
proc getModuleFile(n: PNode): string =
case n.kind
of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.strVal
of nkIdent: result = n.ident.s
of nkSym: result = n.sym.name.s
else:
internalError(n.info, "getModuleFile()")
result = ""
proc traceDeps(d: PDoc, n: PNode) = proc traceDeps(d: PDoc, n: PNode) =
const k = skModule const k = skModule
if d.section[k] != nil: app(d.section[k], ", ") if d.section[k] != nil: app(d.section[k], ", ")
dispA(d.section[k], dispA(d.section[k],
"<a class=\"reference external\" href=\"$1.html\">$1</a>", "<a class=\"reference external\" href=\"$1.html\">$1</a>",
"$1", [toRope(getModuleFile(n))]) "$1", [toRope(getModuleName(n))])
proc generateDoc(d: PDoc, n: PNode) = proc generateDoc(d: PDoc, n: PNode) =
case n.kind case n.kind

View file

@ -16,26 +16,29 @@ import
proc evalImport*(c: PContext, n: PNode): PNode proc evalImport*(c: PContext, n: PNode): PNode
proc evalFrom*(c: PContext, n: PNode): PNode proc evalFrom*(c: PContext, n: PNode): PNode
proc importAllSymbols*(c: PContext, fromMod: PSym) proc importAllSymbols*(c: PContext, fromMod: PSym)
proc getModuleFile*(n: PNode): string
# implementation
proc findModule(info: TLineInfo, modulename: string): string = proc getModuleName*(n: PNode): string =
# returns path to module # This returns a short relative module name without the nim extension
result = options.FindFile(AddFileExt(modulename, nimExt)) # e.g. like "system", "importer" or "somepath/module"
if result == "": Fatal(info, errCannotOpenFile, modulename) # The proc won't perform any checks that the path is actually valid
proc getModuleFile(n: PNode): string =
case n.kind case n.kind
of nkStrLit, nkRStrLit, nkTripleStrLit: of nkStrLit, nkRStrLit, nkTripleStrLit:
result = findModule(n.info, UnixToNativePath(n.strVal)) result = UnixToNativePath(n.strVal)
of nkIdent: of nkIdent:
result = findModule(n.info, n.ident.s) result = n.ident.s
of nkSym: of nkSym:
result = findModule(n.info, n.sym.name.s) result = n.sym.name.s
else: else:
internalError(n.info, "getModuleFile()") internalError(n.info, "getModuleName")
result = "" result = ""
proc checkModuleName*(n: PNode): string =
# This returns the full canonical path for a given module import
var modulename = n.getModuleName
result = findModule(modulename)
if result.len == 0:
Fatal(n.info, errCannotOpenFile, modulename)
proc rawImportSymbol(c: PContext, s: PSym) = proc rawImportSymbol(c: PContext, s: PSym) =
# This does not handle stubs, because otherwise loading on demand would be # This does not handle stubs, because otherwise loading on demand would be
# pointless in practice. So importing stubs is fine here! # pointless in practice. So importing stubs is fine here!
@ -103,7 +106,7 @@ proc importAllSymbols(c: PContext, fromMod: PSym) =
proc evalImport(c: PContext, n: PNode): PNode = proc evalImport(c: PContext, n: PNode): PNode =
result = n result = n
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var f = getModuleFile(n.sons[i]) var f = checkModuleName(n.sons[i])
var m = gImportModule(f) var m = gImportModule(f)
if sfDeprecated in m.flags: if sfDeprecated in m.flags:
Message(n.sons[i].info, warnDeprecated, m.name.s) Message(n.sons[i].info, warnDeprecated, m.name.s)
@ -114,7 +117,7 @@ proc evalImport(c: PContext, n: PNode): PNode =
proc evalFrom(c: PContext, n: PNode): PNode = proc evalFrom(c: PContext, n: PNode): PNode =
result = n result = n
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2)
var f = getModuleFile(n.sons[0]) var f = checkModuleName(n.sons[0])
var m = gImportModule(f) var m = gImportModule(f)
n.sons[0] = newSymNode(m) n.sons[0] = newSymNode(m)
addDecl(c, m) # add symbol to symbol table of module addDecl(c, m) # add symbol to symbol table of module

View file

@ -96,7 +96,7 @@ type
# documentation comments are here too # documentation comments are here too
TLexer* = object of TBaseLexer TLexer* = object of TBaseLexer
filename*: string fileIdx*: int32
indentStack*: seq[int] # the indentation stack indentStack*: seq[int] # the indentation stack
dedent*: int # counter for DED token generation dedent*: int # counter for DED token generation
indentAhead*: int # if > 0 an indendation has already been read indentAhead*: int # if > 0 an indendation has already been read
@ -198,7 +198,7 @@ proc fillToken(L: var TToken) =
proc openLexer(lex: var TLexer, filename: string, inputstream: PLLStream) = proc openLexer(lex: var TLexer, filename: string, inputstream: PLLStream) =
openBaseLexer(lex, inputstream) openBaseLexer(lex, inputstream)
lex.indentStack = @[0] lex.indentStack = @[0]
lex.filename = filename lex.fileIdx = filename.fileInfoIdx
lex.indentAhead = - 1 lex.indentAhead = - 1
inc(lex.Linenumber, inputstream.lineOffset) inc(lex.Linenumber, inputstream.lineOffset)
@ -210,13 +210,13 @@ proc getColumn(L: TLexer): int =
result = getColNumber(L, L.bufPos) result = getColNumber(L, L.bufPos)
proc getLineInfo(L: TLexer): TLineInfo = proc getLineInfo(L: TLexer): TLineInfo =
result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos)) result = newLineInfo(L.fileIdx, L.linenumber, getColNumber(L, L.bufpos))
proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") = proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") =
msgs.Message(getLineInfo(L), msg, arg) msgs.Message(getLineInfo(L), msg, arg)
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart) var info = newLineInfo(L.fileIdx, L.linenumber, pos - L.lineStart)
msgs.Message(info, msg, arg) msgs.Message(info, msg, arg)
proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) = proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =

View file

@ -15,7 +15,8 @@ import
os, lists, condsyms, rodread, rodwrite, ropes, trees, os, lists, condsyms, rodread, rodwrite, ropes, trees,
wordrecg, sem, semdata, idents, passes, docgen, extccomp, wordrecg, sem, semdata, idents, passes, docgen, extccomp,
cgen, ecmasgen, cgen, ecmasgen,
platform, nimconf, importer, passaux, depends, transf, evals, types, idgen platform, nimconf, importer, passaux, depends, transf, evals, types, idgen,
tables
const const
has_LLVM_Backend = false has_LLVM_Backend = false
@ -27,19 +28,16 @@ proc MainCommand*()
# ------------------ module handling ----------------------------------------- # ------------------ module handling -----------------------------------------
type var
TFileModuleRec = tuple[filename: string, module: PSym] compMods = initTable[string, PSym]() # all compiled modules
TFileModuleMap = seq[TFileModuleRec]
var compMods: TFileModuleMap = @[] # all compiled modules
# This expects a normalized module path
proc registerModule(filename: string, module: PSym) = proc registerModule(filename: string, module: PSym) =
compMods.add((filename, module)) compMods[filename] = module
# This expects a normalized module path
proc getModule(filename: string): PSym = proc getModule(filename: string): PSym =
for i in countup(0, high(compMods)): result = compMods[filename]
if sameFile(compMods[i].filename, filename):
return compMods[i].module
proc newModule(filename: string): PSym = proc newModule(filename: string): PSym =
# We cannot call ``newSym`` here, because we have to circumvent the ID # We cannot call ``newSym`` here, because we have to circumvent the ID
@ -71,7 +69,7 @@ proc importModule(filename: string): PSym =
proc CompileModule(filename: string, flags: TSymFlags): PSym = proc CompileModule(filename: string, flags: TSymFlags): PSym =
var rd: PRodReader = nil var rd: PRodReader = nil
var f = addFileExt(filename, nimExt) var f = addFileExt(filename, nimExt)
result = newModule(filename) result = newModule(f)
result.flags = result.flags + flags result.flags = result.flags + flags
if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}: if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}:
rd = handleSymbolFile(result, f) rd = handleSymbolFile(result, f)
@ -178,7 +176,7 @@ proc CommandSuggest =
proc wantMainModule = proc wantMainModule =
if gProjectFull.len == 0: if gProjectFull.len == 0:
Fatal(newLineInfo("command line", 1, 1), errCommandExpectsFilename) Fatal(gCmdLineInfo, errCommandExpectsFilename)
proc MainCommand = proc MainCommand =
appendStr(searchPaths, options.libpath) appendStr(searchPaths, options.libpath)

View file

@ -8,7 +8,7 @@
# #
import import
options, strutils, os options, strutils, os, tables
type type
TMsgKind* = enum TMsgKind* = enum
@ -384,6 +384,11 @@ const
type type
TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints
TNoteKinds* = set[TNoteKind] TNoteKinds* = set[TNoteKind]
TFileInfo*{.final.} = object
fullPath*: string # This is a canonical full filesystem path
projPath*: string # This is relative to the project's root
TLineInfo*{.final.} = object # This is designed to be as small as possible, TLineInfo*{.final.} = object # This is designed to be as small as possible,
# because it is used # because it is used
# in syntax nodes. We safe space here by using # in syntax nodes. We safe space here by using
@ -395,7 +400,45 @@ type
ERecoverableError* = object of EInvalidValue ERecoverableError* = object of EInvalidValue
proc newLineInfo*(filename: string, line, col: int): TLineInfo var
filenameToIndexTbl = initTable[string, int32]()
fileInfos: seq[TFileInfo] = @[]
proc newFileInfo(fullPath, projPath: string): TFileInfo =
result.fullPath = fullPath
result.projPath = projPath
proc fileInfoIdx*(filename: string): int32 =
var
canonical: string
pseudoPath = false
try:
canonical = canonicalizePath(filename)
except:
canonical = filename
# The compiler uses "filenames" such as `command line` or `stdin`
# This flag indicates that we are working with such a path here
pseudoPath = true
if filenameToIndexTbl.hasKey(canonical):
result = filenameToIndexTbl[canonical]
else:
result = fileInfos.len.int32
fileInfos.add(newFileInfo(canonical, if pseudoPath: "" else: canonical.shortenDir))
filenameToIndexTbl[canonical] = result
proc newLineInfo*(fileInfoIdx: int32, line, col: int): TLineInfo =
result.fileIndex = fileInfoIdx
result.line = int16(line)
result.col = int16(col)
proc newLineInfo*(filename: string, line, col: int): TLineInfo {.inline.} =
result = newLineInfo(filename.fileInfoIdx, line, col)
fileInfos.add(newFileInfo("", "command line"))
var gCmdLineInfo* = newLineInfo(int32(0), 1, 1)
proc raiseRecoverableError*() {.noinline, noreturn.} = proc raiseRecoverableError*() {.noinline, noreturn.} =
raise newException(ERecoverableError, "") raise newException(ERecoverableError, "")
@ -423,9 +466,7 @@ proc UnknownLineInfo*(): TLineInfo =
result.fileIndex = -1 result.fileIndex = -1
var var
filenames: seq[tuple[filename: string, fullpath: string]] = @[]
msgContext: seq[TLineInfo] = @[] msgContext: seq[TLineInfo] = @[]
gCmdLineInfo* = newLineInfo("command line", -1, -1)
proc pushInfoContext*(info: TLineInfo) = proc pushInfoContext*(info: TLineInfo) =
msgContext.add(info) msgContext.add(info)
@ -433,31 +474,13 @@ proc pushInfoContext*(info: TLineInfo) =
proc popInfoContext*() = proc popInfoContext*() =
setlen(msgContext, len(msgContext) - 1) setlen(msgContext, len(msgContext) - 1)
proc includeFilename*(f: string): int =
for i in countdown(high(filenames), low(filenames)):
if filenames[i].filename == f:
return i
result = len(filenames)
var fullpath: string
try: fullpath = expandFilename(f)
except: fullpath = ""
filenames.add((filename: f, fullpath: fullpath))
proc newLineInfo(filename: string, line, col: int): TLineInfo =
result.fileIndex = includeFilename(filename)
result.line = int16(line)
result.col = int16(col)
proc ToFilename*(info: TLineInfo): string = proc ToFilename*(info: TLineInfo): string =
if info.fileIndex < 0: result = "???" if info.fileIndex < 0: result = "???"
else: result = filenames[info.fileIndex].filename else: result = fileInfos[info.fileIndex].projPath
proc toFullPath*(info: TLineInfo): string = proc toFullPath*(info: TLineInfo): string =
if info.fileIndex < 0: result = "???" if info.fileIndex < 0: result = "???"
else: result = filenames[info.fileIndex].fullpath else: result = fileInfos[info.fileIndex].fullPath
proc ToLinenumber*(info: TLineInfo): int {.inline.} = proc ToLinenumber*(info: TLineInfo): int {.inline.} =
result = info.line result = info.line

View file

@ -2,6 +2,7 @@
--hint[XDeclaredButNotUsed]=off --hint[XDeclaredButNotUsed]=off
path="llvm" path="llvm"
path="$projectPath/.."
@if llvm_gcc or gcc: @if llvm_gcc or gcc:
# GCC, LLVM and Visual C++ have a problem to optimize some modules. # GCC, LLVM and Visual C++ have a problem to optimize some modules.

View file

@ -70,7 +70,7 @@ proc HandleCmdLine() =
ProcessCmdLine(passCmd1) ProcessCmdLine(passCmd1)
if gProjectName != "": if gProjectName != "":
try: try:
gProjectFull = expandFilename(gProjectName) gProjectFull = canonicalizePath(gProjectName)
except EOS: except EOS:
gProjectFull = gProjectName gProjectFull = gProjectName
var p = splitFile(gProjectFull) var p = splitFile(gProjectFull)

View file

@ -138,12 +138,13 @@ proc getPrefixDir*(): string =
## gets the application directory ## gets the application directory
result = SplitPath(getAppDir()).head result = SplitPath(getAppDir()).head
proc canonicalizePath*(path: string): string =
result = path.expandFilename
when not FileSystemCaseSensitive: result = result.toLower
proc shortenDir*(dir: string): string = proc shortenDir*(dir: string): string =
## returns the interesting part of a dir ## returns the interesting part of a dir
var prefix = getPrefixDir() & dirSep var prefix = getPrefixDir() & dirSep
if startsWith(dir, prefix):
return substr(dir, len(prefix))
prefix = getCurrentDir() & dirSep
if startsWith(dir, prefix): if startsWith(dir, prefix):
return substr(dir, len(prefix)) return substr(dir, len(prefix))
prefix = gProjectPath & dirSep prefix = gProjectPath & dirSep
@ -188,18 +189,20 @@ iterator iterSearchPath*(): string =
it = PStrEntry(it.Next) it = PStrEntry(it.Next)
proc rawFindFile(f: string): string = proc rawFindFile(f: string): string =
if ExistsFile(f): for it in iterSearchPath():
result = f result = JoinPath(it, f)
else: if ExistsFile(result):
for it in iterSearchPath(): return result.canonicalizePath
result = JoinPath(it, f) result = ""
if ExistsFile(result): return
result = ""
proc FindFile*(f: string): string = proc FindFile*(f: string): string =
result = rawFindFile(f) result = rawFindFile(f)
if len(result) == 0: result = rawFindFile(toLower(f)) if len(result) == 0: result = rawFindFile(toLower(f))
proc findModule*(modulename: string): string {.inline.} =
# returns path to module
result = FindFile(AddFileExt(modulename, nimExt))
proc binaryStrSearch*(x: openarray[string], y: string): int = proc binaryStrSearch*(x: openarray[string], y: string): int =
var a = 0 var a = 0
var b = len(x) - 1 var b = len(x) - 1

View file

@ -576,7 +576,9 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
L = 0 L = 0
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')': while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
setlen(r.files, L + 1) setlen(r.files, L + 1)
r.files[L] = decodeStr(r.s, r.pos) var relativePath = decodeStr(r.s, r.pos)
var resolvedPath = relativePath.findModule
r.files[L] = if resolvedPath.len > 0: resolvedPath else: relativePath
inc(r.pos) # skip #10 inc(r.pos) # skip #10
inc(r.line) inc(r.line)
inc(L) inc(L)
@ -628,7 +630,8 @@ proc processRodFile(r: PRodReader, crc: TCrc32) =
r.initIdx = r.pos + 2 # "(\10" r.initIdx = r.pos + 2 # "(\10"
skipSection(r) skipSection(r)
else: else:
MsgWriteln("skipping section: " & $r.pos) MsgWriteln("skipping section: " & section &
" at " & $r.pos & " in " & r.filename)
skipSection(r) skipSection(r)
if r.s[r.pos] == '\x0A': if r.s[r.pos] == '\x0A':
inc(r.pos) inc(r.pos)
@ -788,7 +791,7 @@ proc loadMethods(r: PRodReader) =
proc getModuleIdx(filename: string): int = proc getModuleIdx(filename: string): int =
for i in countup(0, high(gMods)): for i in countup(0, high(gMods)):
if sameFile(gMods[i].filename, filename): return i if gMods[i].filename == filename: return i
result = len(gMods) result = len(gMods)
setlen(gMods, result + 1) setlen(gMods, result + 1)
@ -853,7 +856,7 @@ proc handleSymbolFile(module: PSym, filename: string): PRodReader =
proc GetCRC*(filename: string): TCrc32 = proc GetCRC*(filename: string): TCrc32 =
for i in countup(0, high(gMods)): for i in countup(0, high(gMods)):
if sameFile(gMods[i].filename, filename): return gMods[i].crc if gMods[i].filename == filename: return gMods[i].crc
result = crcFromFile(filename) result = crcFromFile(filename)
#var idx = getModuleIdx(filename) #var idx = getModuleIdx(filename)

View file

@ -95,9 +95,10 @@ const
rodNL = "\x0A" rodNL = "\x0A"
proc addInclDep(w: PRodWriter, dep: string) = proc addInclDep(w: PRodWriter, dep: string) =
var resolved = dep.findModule
encodeVInt(fileIdx(w, dep), w.inclDeps) encodeVInt(fileIdx(w, dep), w.inclDeps)
add(w.inclDeps, " ") add(w.inclDeps, " ")
encodeVInt(crcFromFile(dep), w.inclDeps) encodeVInt(crcFromFile(resolved), w.inclDeps)
add(w.inclDeps, rodNL) add(w.inclDeps, rodNL)
proc pushType(w: PRodWriter, t: PType) = proc pushType(w: PRodWriter, t: PType) =
@ -555,13 +556,13 @@ proc process(c: PPassContext, n: PNode): PNode =
# addInterfaceSym(w, a.sons[j].sym); # addInterfaceSym(w, a.sons[j].sym);
# end # end
of nkImportStmt: of nkImportStmt:
for i in countup(0, sonsLen(n) - 1): addModDep(w, getModuleFile(n.sons[i])) for i in countup(0, sonsLen(n) - 1): addModDep(w, getModuleName(n.sons[i]))
addStmt(w, n) addStmt(w, n)
of nkFromStmt: of nkFromStmt:
addModDep(w, getModuleFile(n.sons[0])) addModDep(w, getModuleName(n.sons[0]))
addStmt(w, n) addStmt(w, n)
of nkIncludeStmt: of nkIncludeStmt:
for i in countup(0, sonsLen(n) - 1): addInclDep(w, getModuleFile(n.sons[i])) for i in countup(0, sonsLen(n) - 1): addInclDep(w, getModuleName(n.sons[i]))
of nkPragma: of nkPragma:
addStmt(w, n) addStmt(w, n)
else: else:
@ -569,7 +570,7 @@ proc process(c: PPassContext, n: PNode): PNode =
proc myOpen(module: PSym, filename: string): PPassContext = proc myOpen(module: PSym, filename: string): PPassContext =
if module.id < 0: InternalError("rodwrite: module ID not set") if module.id < 0: InternalError("rodwrite: module ID not set")
var w = newRodWriter(filename, rodread.GetCRC(filename), module) var w = newRodWriter(filename, rodread.GetCRC(module.info.toFullPath), module)
rawAddInterfaceSym(w, module) rawAddInterfaceSym(w, module)
result = w result = w

View file

@ -135,7 +135,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
if n.sons[paramsPos].kind != nkEmpty: if n.sons[paramsPos].kind != nkEmpty:
removeDefaultParamValues(n.sons[ParamsPos]) removeDefaultParamValues(n.sons[ParamsPos])
semParamList(c, n.sons[ParamsPos], nil, result) semParamList(c, n.sons[ParamsPos], nil, result)
addParams(c, result.typ.n) # XXX: obsoleted - happens in semParamList #
# addParams(c, result.typ.n)
else: else:
result.typ = newTypeS(tyProc, c) result.typ = newTypeS(tyProc, c)
addSon(result.typ, nil) addSon(result.typ, nil)

View file

@ -616,7 +616,8 @@ proc semLambda(c: PContext, n: PNode): PNode =
illFormedAst(n) # process parameters: illFormedAst(n) # process parameters:
if n.sons[paramsPos].kind != nkEmpty: if n.sons[paramsPos].kind != nkEmpty:
semParamList(c, n.sons[ParamsPos], nil, s) semParamList(c, n.sons[ParamsPos], nil, s)
addParams(c, s.typ.n) # XXX: obsoleted - happens in semParamList
# addParams(c, s.typ.n)
ParamsTypeCheck(c, s.typ) ParamsTypeCheck(c, s.typ)
else: else:
s.typ = newTypeS(tyProc, c) s.typ = newTypeS(tyProc, c)
@ -665,7 +666,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
n.sons[genericParamsPos] = gp n.sons[genericParamsPos] = gp
# check for semantics again: # check for semantics again:
semParamList(c, n.sons[ParamsPos], nil, s) semParamList(c, n.sons[ParamsPos], nil, s)
addParams(c, s.typ.n) # XXX: obsoleted - happens in semParamList
# addParams(c, s.typ.n)
else: else:
s.typ = newTypeS(tyProc, c) s.typ = newTypeS(tyProc, c)
addSon(s.typ, nil) addSon(s.typ, nil)
@ -795,8 +797,8 @@ proc evalInclude(c: PContext, n: PNode): PNode =
result = newNodeI(nkStmtList, n.info) result = newNodeI(nkStmtList, n.info)
addSon(result, n) addSon(result, n)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var f = getModuleFile(n.sons[i]) var f = checkModuleName(n.sons[i])
var fileIndex = includeFilename(f) var fileIndex = f.fileInfoIdx
if ContainsOrIncl(c.includedFiles, fileIndex): if ContainsOrIncl(c.includedFiles, fileIndex):
GlobalError(n.info, errRecursiveDependencyX, f) GlobalError(n.info, errRecursiveDependencyX, f)
addSon(result, semStmt(c, gIncludeFile(f))) addSon(result, semStmt(c, gIncludeFile(f)))

View file

@ -185,7 +185,8 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
# use ``stmt`` as implicit result type # use ``stmt`` as implicit result type
s.typ.sons[0] = newTypeS(tyStmt, c) s.typ.sons[0] = newTypeS(tyStmt, c)
s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0]) s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0])
addParams(c, s.typ.n) # resolve parameters: # XXX: obsoleted - happens in semParamList #
# addParams(c, s.typ.n) # resolve parameters:
var toBind = initIntSet() var toBind = initIntSet()
n.sons[bodyPos] = resolveTemplateParams(c, n.sons[bodyPos], false, toBind) n.sons[bodyPos] = resolveTemplateParams(c, n.sons[bodyPos], false, toBind)
if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}: if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}:

View file

@ -569,6 +569,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
LocalError(a.sons[j].info, errAttemptToRedefine, arg.name.s) LocalError(a.sons[j].info, errAttemptToRedefine, arg.name.s)
addSon(result.n, newSymNode(arg)) addSon(result.n, newSymNode(arg))
addSon(result, typ) addSon(result, typ)
addDecl(c, arg)
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
var r = paramType(c, n.sons[0], genericParams, cl) var r = paramType(c, n.sons[0], genericParams, cl)
# turn explicit 'void' return type into 'nil' because the rest of the # turn explicit 'void' return type into 'nil' because the rest of the
@ -711,11 +713,13 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkDistinctTy: result = semDistinct(c, n, prev) of nkDistinctTy: result = semDistinct(c, n, prev)
of nkProcTy: of nkProcTy:
checkSonsLen(n, 2) checkSonsLen(n, 2)
openScope(c.tab)
result = semProcTypeNode(c, n.sons[0], nil, prev) result = semProcTypeNode(c, n.sons[0], nil, prev)
# dummy symbol for `pragma`: # dummy symbol for `pragma`:
var s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c) var s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
s.typ = result s.typ = result
pragma(c, s, n.sons[1], procTypePragmas) pragma(c, s, n.sons[1], procTypePragmas)
closeScope(c.tab)
of nkEnumTy: result = semEnum(c, n, prev) of nkEnumTy: result = semEnum(c, n, prev)
of nkType: result = n.typ of nkType: result = n.typ
of nkStmtListType: result = semStmtListType(c, n, prev) of nkStmtListType: result = semStmtListType(c, n, prev)

View file

@ -713,7 +713,7 @@ proc matches*(c: PContext, n: PNode, m: var TCandidate) =
when false: when false:
if sfSystemModule notin c.module.flags: if sfSystemModule notin c.module.flags:
if includeFilename("temp.nim") == c.module.info.fileIndex: if fileInfoIdx("temp.nim") == c.module.info.fileIndex:
echo "########################" echo "########################"
echo m.call.renderTree echo m.call.renderTree
for i in 1..m.call.len-1: for i in 1..m.call.len-1:

View file

@ -107,7 +107,7 @@ clang.options.size = "-Os"
# Configuration for the Visual C/C++ compiler: # Configuration for the Visual C/C++ compiler:
vcc.options.linker = "/DEBUG /Zi /Fd\"$projectName.pdb\" /F33554432" # set the stack size to 8 MB vcc.options.linker = "/DEBUG /Zi /Fd\"$projectName.pdb\" /F33554432" # set the stack size to 8 MB
vcc.options.debug = "/RTC1 /Zi /Fd\"$projectName.pdb\"" vcc.options.debug = "/Zi /Fd\"$projectName.pdb\""
vcc.options.always = "/nologo" vcc.options.always = "/nologo"
vcc.options.speed = "/Ox /arch:SSE2" vcc.options.speed = "/Ox /arch:SSE2"
vcc.options.size = "/O1" vcc.options.size = "/O1"

View file

@ -567,26 +567,45 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} =
result = path[0] == '/' result = path[0] == '/'
proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1".} = proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1".} =
## Returns True if both pathname arguments refer to the same file or ## Returns True if both pathname arguments refer to the same physical
## directory (as indicated by device number and i-node number). ## file or directory. Raises an exception if any of the files does not
## Raises an exception if an stat() call on either pathname fails. ## exist or information about it can not be obtained.
##
## This proc will return true if given two alternative hard-linked or
## sym-linked paths to the same file or directory.
when defined(Windows): when defined(Windows):
var var success = true
a, b: TWin32FindData
var resA = findfirstFileA(path1, a) template OpenHandle(path: expr): expr =
var resB = findfirstFileA(path2, b) CreateFileA(path, 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or
if resA != -1 and resB != -1: FILE_SHARE_WRITE, nil, OPEN_EXISTING,
result = $a.cFileName == $b.cFileName FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL, 0)
else:
# work around some ``findfirstFileA`` bugs var f1 = OpenHandle(path1)
result = cmpPaths(path1, path2) == 0 var f2 = OpenHandle(path2)
if resA != -1: findclose(resA)
if resB != -1: findclose(resB) if f1 != INVALID_HANDLE_VALUE and f2 != INVALID_HANDLE_VALUE:
var fi1, fi2: TBY_HANDLE_FILE_INFORMATION
if GetFileInformationByHandle(f1, addr(fi1)) != 0 and
GetFileInformationByHandle(f2, addr(fi2)) != 0:
result = fi1.dwVolumeSerialNumber == fi2.dwVolumeSerialNumber and
fi1.nFileIndexHigh == fi2.nFileIndexHigh and
fi1.nFileIndexLow == fi2.nFileIndexLow
else: success = false
else: success = false
discard CloseHandle(f1)
discard CloseHandle(f2)
if not success:
OSError()
else: else:
var var
a, b: TStat a, b: TStat
if stat(path1, a) < 0'i32 or stat(path2, b) < 0'i32: if stat(path1, a) < 0'i32 or stat(path2, b) < 0'i32:
result = cmpPaths(path1, path2) == 0 # be consistent with Windows OSError()
else: else:
result = a.st_dev == b.st_dev and a.st_ino == b.st_ino result = a.st_dev == b.st_dev and a.st_ino == b.st_ino

View file

@ -302,7 +302,7 @@ when not defined(ECMAScript):
posix_gettimeofday(a) posix_gettimeofday(a)
result = toFloat(a.tv_sec) + toFloat(a.tv_usec)*0.00_0001 result = toFloat(a.tv_sec) + toFloat(a.tv_usec)*0.00_0001
elif defined(windows): elif defined(windows):
var f: winlean.Filetime var f: winlean.TFiletime
GetSystemTimeAsFileTime(f) GetSystemTimeAsFileTime(f)
var i64 = rdFileTime(f) - epochDiff var i64 = rdFileTime(f) - epochDiff
var secs = i64 div rateDiff var secs = i64 div rateDiff

View file

@ -70,6 +70,10 @@ template test*(name: expr, body: stmt): stmt =
TestSetupIMPL() TestSetupIMPL()
body body
except:
checkpoint("Unhandled exception: " & getCurrentExceptionMsg())
fail()
finally: finally:
TestTeardownIMPL() TestTeardownIMPL()
testDone name, TestStatusIMPL testDone name, TestStatusIMPL

View file

@ -47,6 +47,22 @@ type
dwProcessId*: int32 dwProcessId*: int32
dwThreadId*: int32 dwThreadId*: int32
TFILETIME* {.final, pure.} = object ## CANNOT BE int64 BECAUSE OF ALIGNMENT
dwLowDateTime*: DWORD
dwHighDateTime*: DWORD
TBY_HANDLE_FILE_INFORMATION* {.final, pure.} = object
dwFileAttributes*: DWORD
ftCreationTime*: TFILETIME
ftLastAccessTime*: TFILETIME
ftLastWriteTime*: TFILETIME
dwVolumeSerialNumber*: DWORD
nFileSizeHigh*: DWORD
nFileSizeLow*: DWORD
nNumberOfLinks*: DWORD
nFileIndexHigh*: DWORD
nFileIndexLow*: DWORD
const const
STARTF_USESHOWWINDOW* = 1'i32 STARTF_USESHOWWINDOW* = 1'i32
STARTF_USESTDHANDLES* = 256'i32 STARTF_USESTDHANDLES* = 256'i32
@ -149,14 +165,11 @@ const
MAX_PATH* = 260 MAX_PATH* = 260
type type
FILETIME* {.final, pure.} = object ## CANNOT BE int64 BECAUSE OF ALIGNMENT
dwLowDateTime*: int32
dwHighDateTime*: int32
TWIN32_FIND_DATA* {.pure.} = object TWIN32_FIND_DATA* {.pure.} = object
dwFileAttributes*: int32 dwFileAttributes*: int32
ftCreationTime*: FILETIME ftCreationTime*: TFILETIME
ftLastAccessTime*: FILETIME ftLastAccessTime*: TFILETIME
ftLastWriteTime*: FILETIME ftLastWriteTime*: TFILETIME
nFileSizeHigh*: int32 nFileSizeHigh*: int32
nFileSizeLow*: int32 nFileSizeLow*: int32
dwReserved0: int32 dwReserved0: int32
@ -192,13 +205,13 @@ proc FreeEnvironmentStringsA*(para1: cstring): int32 {.
proc GetCommandLineA*(): CString {.importc, stdcall, dynlib: "kernel32".} proc GetCommandLineA*(): CString {.importc, stdcall, dynlib: "kernel32".}
proc rdFileTime*(f: FILETIME): int64 = proc rdFileTime*(f: TFILETIME): int64 =
result = ze64(f.dwLowDateTime) or (ze64(f.dwHighDateTime) shl 32) result = ze64(f.dwLowDateTime) or (ze64(f.dwHighDateTime) shl 32)
proc rdFileSize*(f: TWin32FindData): int64 = proc rdFileSize*(f: TWin32FindData): int64 =
result = ze64(f.nFileSizeLow) or (ze64(f.nFileSizeHigh) shl 32) result = ze64(f.nFileSizeLow) or (ze64(f.nFileSizeHigh) shl 32)
proc GetSystemTimeAsFileTime*(lpSystemTimeAsFileTime: var FileTime) {. proc GetSystemTimeAsFileTime*(lpSystemTimeAsFileTime: var TFILETIME) {.
importc: "GetSystemTimeAsFileTime", dynlib: "kernel32", stdcall.} importc: "GetSystemTimeAsFileTime", dynlib: "kernel32", stdcall.}
proc Sleep*(dwMilliseconds: int32){.stdcall, dynlib: "kernel32", proc Sleep*(dwMilliseconds: int32){.stdcall, dynlib: "kernel32",
@ -209,6 +222,10 @@ proc ShellExecute*(HWND: THandle, lpOperation, lpFile,
nShowCmd: int32): THandle{. nShowCmd: int32): THandle{.
stdcall, dynlib: "shell32.dll", importc: "ShellExecuteA".} stdcall, dynlib: "shell32.dll", importc: "ShellExecuteA".}
proc GetFileInformationByHandle*(hFile: THandle,
lpFileInformation: ptr TBY_HANDLE_FILE_INFORMATION): WINBOOL{.
stdcall, dynlib: "kernel32", importc: "GetFileInformationByHandle".}
const const
WSADESCRIPTION_LEN* = 256 WSADESCRIPTION_LEN* = 256
WSASYS_STATUS_LEN* = 128 WSASYS_STATUS_LEN* = 128
@ -410,6 +427,9 @@ const
GENERIC_READ* = 0x80000000'i32 GENERIC_READ* = 0x80000000'i32
GENERIC_ALL* = 0x10000000'i32 GENERIC_ALL* = 0x10000000'i32
FILE_SHARE_READ* = 1'i32 FILE_SHARE_READ* = 1'i32
FILE_SHARE_DELETE* = 4'i32
FILE_SHARE_WRITE* = 2'i32
CREATE_ALWAYS* = 2'i32 CREATE_ALWAYS* = 2'i32
OPEN_EXISTING* = 3'i32 OPEN_EXISTING* = 3'i32
FILE_BEGIN* = 0'i32 FILE_BEGIN* = 0'i32
@ -421,6 +441,8 @@ const
FILE_MAP_WRITE* = 2'i32 FILE_MAP_WRITE* = 2'i32
INVALID_FILE_SIZE* = -1'i32 INVALID_FILE_SIZE* = -1'i32
FILE_FLAG_BACKUP_SEMANTICS* = 33554432'i32
proc CreateFileA*(lpFileName: cstring, dwDesiredAccess, dwShareMode: DWORD, proc CreateFileA*(lpFileName: cstring, dwDesiredAccess, dwShareMode: DWORD,
lpSecurityAttributes: pointer, lpSecurityAttributes: pointer,
dwCreationDisposition, dwFlagsAndAttributes: DWORD, dwCreationDisposition, dwFlagsAndAttributes: DWORD,

View file

@ -35,3 +35,6 @@ var y*: type(t2(100)) = "test"
proc t6*(x: type(t3(0))): type(t1(0)) = proc t6*(x: type(t3(0))): type(t1(0)) =
result = $x result = $x
proc t7*(x: int): type($x) =
result = "test"