Merge branch 'master' of github.com:Araq/Nimrod
This commit is contained in:
commit
98ed7fbf16
24 changed files with 223 additions and 146 deletions
|
|
@ -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 =
|
||||||
|
|
|
||||||
|
|
@ -459,9 +459,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||||
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
|
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
|
||||||
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)
|
|
||||||
|
|
|
||||||
|
|
@ -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])
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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) =
|
||||||
|
|
|
||||||
|
|
@ -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) =
|
||||||
|
compMods[filename] = module
|
||||||
|
|
||||||
proc registerModule(filename: string, module: PSym) =
|
# This expects a normalized module path
|
||||||
compMods.add((filename, module))
|
proc getModule(filename: string): PSym =
|
||||||
|
result = compMods[filename]
|
||||||
proc getModule(filename: string): PSym =
|
|
||||||
for i in countup(0, high(compMods)):
|
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -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 =
|
proc ToFilename*(info: TLineInfo): string =
|
||||||
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 =
|
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -70,14 +70,14 @@ 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)
|
||||||
gProjectPath = p.dir
|
gProjectPath = p.dir
|
||||||
gProjectName = p.name
|
gProjectName = p.name
|
||||||
else:
|
else:
|
||||||
gProjectPath = getCurrentDir()
|
gProjectPath = getCurrentDir()
|
||||||
LoadConfigs(DefaultConfig) # load all config files
|
LoadConfigs(DefaultConfig) # load all config files
|
||||||
# now process command line arguments again, because some options in the
|
# now process command line arguments again, because some options in the
|
||||||
# command line can overwite the config file's settings
|
# command line can overwite the config file's settings
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -185,21 +186,23 @@ iterator iterSearchPath*(): string =
|
||||||
var it = PStrEntry(SearchPaths.head)
|
var it = PStrEntry(SearchPaths.head)
|
||||||
while it != nil:
|
while it != nil:
|
||||||
yield it.data
|
yield it.data
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -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,11 +791,11 @@ 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)
|
||||||
|
|
||||||
proc checkDep(filename: string): TReasonForRecompile =
|
proc checkDep(filename: string): TReasonForRecompile =
|
||||||
assert(not isNil(filename))
|
assert(not isNil(filename))
|
||||||
var idx = getModuleIdx(filename)
|
var idx = getModuleIdx(filename)
|
||||||
if gMods[idx].reason != rrEmpty:
|
if gMods[idx].reason != rrEmpty:
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -87,17 +87,18 @@ proc newRodWriter(modfilename: string, crc: TCrc32, module: PSym): PRodWriter =
|
||||||
result.init = ""
|
result.init = ""
|
||||||
result.data = newStringOfCap(12_000)
|
result.data = newStringOfCap(12_000)
|
||||||
|
|
||||||
proc addModDep(w: PRodWriter, dep: string) =
|
proc addModDep(w: PRodWriter, dep: string) =
|
||||||
if w.modDeps.len != 0: add(w.modDeps, ' ')
|
if w.modDeps.len != 0: add(w.modDeps, ' ')
|
||||||
encodeVInt(fileIdx(w, dep), w.modDeps)
|
encodeVInt(fileIdx(w, dep), w.modDeps)
|
||||||
|
|
||||||
const
|
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,21 +556,21 @@ 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:
|
||||||
nil
|
nil
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)))
|
||||||
|
|
|
||||||
|
|
@ -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}:
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
result = semProcTypeNode(c, n.sons[0], nil, prev)
|
openScope(c.tab)
|
||||||
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,12 +222,16 @@ 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
|
||||||
FD_SETSIZE* = 64
|
FD_SETSIZE* = 64
|
||||||
MSG_PEEK* = 2
|
MSG_PEEK* = 2
|
||||||
|
|
||||||
INADDR_ANY* = 0
|
INADDR_ANY* = 0
|
||||||
INADDR_LOOPBACK* = 0x7F000001
|
INADDR_LOOPBACK* = 0x7F000001
|
||||||
INADDR_BROADCAST* = -1
|
INADDR_BROADCAST* = -1
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue