Merge pull request #2961 from Perelandric/rename_writeLn

Renamed writeln to writeLine. Issue #2958
This commit is contained in:
Dominik Picheta 2015-06-20 16:25:37 +01:00
commit e74012b396
71 changed files with 815 additions and 801 deletions

View file

@ -452,7 +452,7 @@ proc debug(n: PSym) =
elif n.kind == skUnknown: elif n.kind == skUnknown:
msgWriteln("skUnknown") msgWriteln("skUnknown")
else: else:
#writeln(stdout, $symToYaml(n, 0, 1)) #writeLine(stdout, $symToYaml(n, 0, 1))
msgWriteln("$1_$2: $3, $4, $5, $6" % [ msgWriteln("$1_$2: $3, $4, $5, $6" % [
n.name.s, $n.id, $flagsToStr(n.flags), $flagsToStr(n.loc.flags), n.name.s, $n.id, $flagsToStr(n.flags), $flagsToStr(n.loc.flags),
$lineInfoToStr(n.info), $n.kind]) $lineInfoToStr(n.info), $n.kind])

View file

@ -596,7 +596,7 @@ proc externalFileChanged(filename: string): bool =
result = true result = true
if result: if result:
if open(f, crcFile, fmWrite): if open(f, crcFile, fmWrite):
f.writeln($currentCrc) f.writeLine($currentCrc)
close(f) close(f)
proc addExternalFileToCompile*(filename: string) = proc addExternalFileToCompile*(filename: string) =

View file

@ -18,26 +18,26 @@ const
when debugIds: when debugIds:
import intsets import intsets
var usedIds = initIntSet() var usedIds = initIntSet()
proc registerID*(id: PIdObj) = proc registerID*(id: PIdObj) =
when debugIds: when debugIds:
if id.id == -1 or containsOrIncl(usedIds, id.id): if id.id == -1 or containsOrIncl(usedIds, id.id):
internalError("ID already used: " & $id.id) internalError("ID already used: " & $id.id)
proc getID*(): int {.inline.} = proc getID*(): int {.inline.} =
result = gFrontEndId result = gFrontEndId
inc(gFrontEndId) inc(gFrontEndId)
proc backendId*(): int {.inline.} = proc backendId*(): int {.inline.} =
result = gBackendId result = gBackendId
inc(gBackendId) inc(gBackendId)
proc setId*(id: int) {.inline.} = proc setId*(id: int) {.inline.} =
gFrontEndId = max(gFrontEndId, id + 1) gFrontEndId = max(gFrontEndId, id + 1)
proc idSynchronizationPoint*(idRange: int) = proc idSynchronizationPoint*(idRange: int) =
gFrontEndId = (gFrontEndId div idRange + 1) * idRange + 1 gFrontEndId = (gFrontEndId div idRange + 1) * idRange + 1
proc toGid(f: string): string = proc toGid(f: string): string =
@ -48,10 +48,10 @@ proc toGid(f: string): string =
proc saveMaxIds*(project: string) = proc saveMaxIds*(project: string) =
var f = open(project.toGid, fmWrite) var f = open(project.toGid, fmWrite)
f.writeln($gFrontEndId) f.writeLine($gFrontEndId)
f.writeln($gBackendId) f.writeLine($gBackendId)
f.close() f.close()
proc loadMaxIds*(project: string) = proc loadMaxIds*(project: string) =
var f: File var f: File
if open(f, project.toGid, fmRead): if open(f, project.toGid, fmRead):

View file

@ -593,7 +593,7 @@ var
proc suggestWriteln*(s: string) = proc suggestWriteln*(s: string) =
if eStdOut in errorOutputs: if eStdOut in errorOutputs:
if isNil(writelnHook): writeln(stdout, s) if isNil(writelnHook): writeLine(stdout, s)
else: writelnHook(s) else: writelnHook(s)
proc msgQuit*(x: int8) = quit x proc msgQuit*(x: int8) = quit x
@ -688,7 +688,7 @@ var gTrackPos*: TLineInfo
proc outWriteln*(s: string) = proc outWriteln*(s: string) =
## Writes to stdout. Always. ## Writes to stdout. Always.
if eStdOut in errorOutputs: writeln(stdout, s) if eStdOut in errorOutputs: writeLine(stdout, s)
proc msgWriteln*(s: string) = proc msgWriteln*(s: string) =
## Writes to stdout. If --stdout option is given, writes to stderr instead. ## Writes to stdout. If --stdout option is given, writes to stderr instead.
@ -698,9 +698,9 @@ proc msgWriteln*(s: string) =
if not isNil(writelnHook): if not isNil(writelnHook):
writelnHook(s) writelnHook(s)
elif optStdout in gGlobalOptions: elif optStdout in gGlobalOptions:
if eStdErr in errorOutputs: writeln(stderr, s) if eStdErr in errorOutputs: writeLine(stderr, s)
else: else:
if eStdOut in errorOutputs: writeln(stdout, s) if eStdOut in errorOutputs: writeLine(stdout, s)
macro callIgnoringStyle(theProc: typed, first: typed, macro callIgnoringStyle(theProc: typed, first: typed,
args: varargs[expr]): stmt = args: varargs[expr]): stmt =
@ -735,13 +735,13 @@ template styledMsgWriteln*(args: varargs[expr]) =
if not isNil(writelnHook): if not isNil(writelnHook):
callIgnoringStyle(callWritelnHook, nil, args) callIgnoringStyle(callWritelnHook, nil, args)
elif optStdout in gGlobalOptions: elif optStdout in gGlobalOptions:
if eStdErr in errorOutputs: callIgnoringStyle(writeln, stderr, args) if eStdErr in errorOutputs: callIgnoringStyle(writeLine, stderr, args)
else: else:
if eStdOut in errorOutputs: if eStdOut in errorOutputs:
if optUseColors in gGlobalOptions: if optUseColors in gGlobalOptions:
callStyledEcho(args) callStyledEcho(args)
else: else:
callIgnoringStyle(writeln, stdout, args) callIgnoringStyle(writeLine, stdout, args)
proc coordToStr(coord: int): string = proc coordToStr(coord: int): string =
if coord == -1: result = "???" if coord == -1: result = "???"

View file

@ -82,7 +82,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
proc handleCmdLine() = proc handleCmdLine() =
if paramCount() == 0: if paramCount() == 0:
stdout.writeln(Usage) stdout.writeLine(Usage)
else: else:
processCmdLine(passCmd1, "") processCmdLine(passCmd1, "")
if gProjectName != "": if gProjectName != "":

View file

@ -304,7 +304,7 @@ proc completeGeneratedFilePath*(f: string, createSubDir: bool = true): string =
when noTimeMachine: when noTimeMachine:
excludeDirFromTimeMachine(subdir) excludeDirFromTimeMachine(subdir)
except OSError: except OSError:
writeln(stdout, "cannot create directory: " & subdir) writeLine(stdout, "cannot create directory: " & subdir)
quit(1) quit(1)
result = joinPath(subdir, tail) result = joinPath(subdir, tail)
#echo "completeGeneratedFilePath(", f, ") = ", result #echo "completeGeneratedFilePath(", f, ") = ", result

View file

@ -12,7 +12,7 @@
# Reading and writing binary files are really hard to debug. Therefore we use # Reading and writing binary files are really hard to debug. Therefore we use
# a "creative" text/binary hybrid format. ROD-files are more efficient # a "creative" text/binary hybrid format. ROD-files are more efficient
# to process because symbols can be loaded on demand. # to process because symbols can be loaded on demand.
# #
# A ROD file consists of: # A ROD file consists of:
# #
# - a header: # - a header:
@ -44,7 +44,7 @@
# ) # )
# - a compiler proc section: # - a compiler proc section:
# COMPILERPROCS( # COMPILERPROCS(
# identifier1 id\n # id is the symbol's id # identifier1 id\n # id is the symbol's id
# ) # )
# - an index consisting of (ID, linenumber)-pairs: # - an index consisting of (ID, linenumber)-pairs:
# INDEX( # INDEX(
@ -52,7 +52,7 @@
# id-diff idx-diff\n # id-diff idx-diff\n
# ) # )
# #
# Since the whole index has to be read in advance, we compress it by # Since the whole index has to be read in advance, we compress it by
# storing the integer differences to the last entry instead of using the # storing the integer differences to the last entry instead of using the
# real numbers. # real numbers.
# #
@ -88,11 +88,11 @@
# by using a mem'mapped file. # by using a mem'mapped file.
# #
import import
os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms, os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms,
ropes, idents, securehash, idgen, types, rodutils, memfiles ropes, idents, securehash, idgen, types, rodutils, memfiles
type type
TReasonForRecompile* = enum ## all the reasons that can trigger recompilation TReasonForRecompile* = enum ## all the reasons that can trigger recompilation
rrEmpty, # dependencies not yet computed rrEmpty, # dependencies not yet computed
rrNone, # no need to recompile rrNone, # no need to recompile
@ -104,14 +104,14 @@ type
rrInclDeps, # an include has changed rrInclDeps, # an include has changed
rrModDeps # a module this module depends on has been changed rrModDeps # a module this module depends on has been changed
const const
reasonToFrmt*: array[TReasonForRecompile, string] = ["", reasonToFrmt*: array[TReasonForRecompile, string] = ["",
"no need to recompile: $1", "symbol file for $1 does not exist", "no need to recompile: $1", "symbol file for $1 does not exist",
"symbol file for $1 has the wrong version", "symbol file for $1 has the wrong version",
"file edited since last compilation: $1", "file edited since last compilation: $1",
"list of conditional symbols changed for: $1", "list of conditional symbols changed for: $1",
"list of options changed for: $1", "list of options changed for: $1",
"an include file edited: $1", "an include file edited: $1",
"a module $1 depends on has changed"] "a module $1 depends on has changed"]
type type
@ -120,7 +120,7 @@ type
tab*: TIITable tab*: TIITable
r*: string # writers use this r*: string # writers use this
offset*: int # readers use this offset*: int # readers use this
TRodReader* = object of RootObj TRodReader* = object of RootObj
pos: int # position; used for parsing pos: int # position; used for parsing
s: cstring # mmap'ed file contents s: cstring # mmap'ed file contents
@ -142,7 +142,7 @@ type
methods*: TSymSeq methods*: TSymSeq
origFile: string origFile: string
inViewMode: bool inViewMode: bool
PRodReader* = ref TRodReader PRodReader* = ref TRodReader
var rodCompilerprocs*: TStrTable var rodCompilerprocs*: TStrTable
@ -161,16 +161,16 @@ proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym
# `info` is only used for debugging purposes # `info` is only used for debugging purposes
proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType
proc decodeLineInfo(r: PRodReader, info: var TLineInfo) = proc decodeLineInfo(r: PRodReader, info: var TLineInfo) =
if r.s[r.pos] == '?': if r.s[r.pos] == '?':
inc(r.pos) inc(r.pos)
if r.s[r.pos] == ',': info.col = -1'i16 if r.s[r.pos] == ',': info.col = -1'i16
else: info.col = int16(decodeVInt(r.s, r.pos)) else: info.col = int16(decodeVInt(r.s, r.pos))
if r.s[r.pos] == ',': if r.s[r.pos] == ',':
inc(r.pos) inc(r.pos)
if r.s[r.pos] == ',': info.line = -1'i16 if r.s[r.pos] == ',': info.line = -1'i16
else: info.line = int16(decodeVInt(r.s, r.pos)) else: info.line = int16(decodeVInt(r.s, r.pos))
if r.s[r.pos] == ',': if r.s[r.pos] == ',':
inc(r.pos) inc(r.pos)
info = newLineInfo(r.files[decodeVInt(r.s, r.pos)], info.line, info.col) info = newLineInfo(r.files[decodeVInt(r.s, r.pos)], info.line, info.col)
@ -188,56 +188,56 @@ proc skipNode(r: PRodReader) =
inc pos inc pos
r.pos = pos+1 # skip ')' r.pos = pos+1 # skip ')'
proc decodeNodeLazyBody(r: PRodReader, fInfo: TLineInfo, proc decodeNodeLazyBody(r: PRodReader, fInfo: TLineInfo,
belongsTo: PSym): PNode = belongsTo: PSym): PNode =
result = nil result = nil
if r.s[r.pos] == '(': if r.s[r.pos] == '(':
inc(r.pos) inc(r.pos)
if r.s[r.pos] == ')': if r.s[r.pos] == ')':
inc(r.pos) inc(r.pos)
return # nil node return # nil node
result = newNodeI(TNodeKind(decodeVInt(r.s, r.pos)), fInfo) result = newNodeI(TNodeKind(decodeVInt(r.s, r.pos)), fInfo)
decodeLineInfo(r, result.info) decodeLineInfo(r, result.info)
if r.s[r.pos] == '$': if r.s[r.pos] == '$':
inc(r.pos) inc(r.pos)
result.flags = cast[TNodeFlags](int32(decodeVInt(r.s, r.pos))) result.flags = cast[TNodeFlags](int32(decodeVInt(r.s, r.pos)))
if r.s[r.pos] == '^': if r.s[r.pos] == '^':
inc(r.pos) inc(r.pos)
var id = decodeVInt(r.s, r.pos) var id = decodeVInt(r.s, r.pos)
result.typ = rrGetType(r, id, result.info) result.typ = rrGetType(r, id, result.info)
case result.kind case result.kind
of nkCharLit..nkInt64Lit: of nkCharLit..nkInt64Lit:
if r.s[r.pos] == '!': if r.s[r.pos] == '!':
inc(r.pos) inc(r.pos)
result.intVal = decodeVBiggestInt(r.s, r.pos) result.intVal = decodeVBiggestInt(r.s, r.pos)
of nkFloatLit..nkFloat64Lit: of nkFloatLit..nkFloat64Lit:
if r.s[r.pos] == '!': if r.s[r.pos] == '!':
inc(r.pos) inc(r.pos)
var fl = decodeStr(r.s, r.pos) var fl = decodeStr(r.s, r.pos)
result.floatVal = parseFloat(fl) result.floatVal = parseFloat(fl)
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
if r.s[r.pos] == '!': if r.s[r.pos] == '!':
inc(r.pos) inc(r.pos)
result.strVal = decodeStr(r.s, r.pos) result.strVal = decodeStr(r.s, r.pos)
else: else:
result.strVal = "" # BUGFIX result.strVal = "" # BUGFIX
of nkIdent: of nkIdent:
if r.s[r.pos] == '!': if r.s[r.pos] == '!':
inc(r.pos) inc(r.pos)
var fl = decodeStr(r.s, r.pos) var fl = decodeStr(r.s, r.pos)
result.ident = getIdent(fl) result.ident = getIdent(fl)
else: else:
internalError(result.info, "decodeNode: nkIdent") internalError(result.info, "decodeNode: nkIdent")
of nkSym: of nkSym:
if r.s[r.pos] == '!': if r.s[r.pos] == '!':
inc(r.pos) inc(r.pos)
var id = decodeVInt(r.s, r.pos) var id = decodeVInt(r.s, r.pos)
result.sym = rrGetSym(r, id, result.info) result.sym = rrGetSym(r, id, result.info)
else: else:
internalError(result.info, "decodeNode: nkSym") internalError(result.info, "decodeNode: nkSym")
else: else:
var i = 0 var i = 0
while r.s[r.pos] != ')': while r.s[r.pos] != ')':
if belongsTo != nil and i == bodyPos: if belongsTo != nil and i == bodyPos:
addSonNilAllowed(result, nil) addSonNilAllowed(result, nil)
belongsTo.offset = r.pos belongsTo.offset = r.pos
@ -252,93 +252,93 @@ proc decodeNodeLazyBody(r: PRodReader, fInfo: TLineInfo,
proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode = proc decodeNode(r: PRodReader, fInfo: TLineInfo): PNode =
result = decodeNodeLazyBody(r, fInfo, nil) result = decodeNodeLazyBody(r, fInfo, nil)
proc decodeLoc(r: PRodReader, loc: var TLoc, info: TLineInfo) = proc decodeLoc(r: PRodReader, loc: var TLoc, info: TLineInfo) =
if r.s[r.pos] == '<': if r.s[r.pos] == '<':
inc(r.pos) inc(r.pos)
if r.s[r.pos] in {'0'..'9', 'a'..'z', 'A'..'Z'}: if r.s[r.pos] in {'0'..'9', 'a'..'z', 'A'..'Z'}:
loc.k = TLocKind(decodeVInt(r.s, r.pos)) loc.k = TLocKind(decodeVInt(r.s, r.pos))
else: else:
loc.k = low(loc.k) loc.k = low(loc.k)
if r.s[r.pos] == '*': if r.s[r.pos] == '*':
inc(r.pos) inc(r.pos)
loc.s = TStorageLoc(decodeVInt(r.s, r.pos)) loc.s = TStorageLoc(decodeVInt(r.s, r.pos))
else: else:
loc.s = low(loc.s) loc.s = low(loc.s)
if r.s[r.pos] == '$': if r.s[r.pos] == '$':
inc(r.pos) inc(r.pos)
loc.flags = cast[TLocFlags](int32(decodeVInt(r.s, r.pos))) loc.flags = cast[TLocFlags](int32(decodeVInt(r.s, r.pos)))
else: else:
loc.flags = {} loc.flags = {}
if r.s[r.pos] == '^': if r.s[r.pos] == '^':
inc(r.pos) inc(r.pos)
loc.t = rrGetType(r, decodeVInt(r.s, r.pos), info) loc.t = rrGetType(r, decodeVInt(r.s, r.pos), info)
else: else:
loc.t = nil loc.t = nil
if r.s[r.pos] == '!': if r.s[r.pos] == '!':
inc(r.pos) inc(r.pos)
loc.r = rope(decodeStr(r.s, r.pos)) loc.r = rope(decodeStr(r.s, r.pos))
else: else:
loc.r = nil loc.r = nil
if r.s[r.pos] == '>': inc(r.pos) if r.s[r.pos] == '>': inc(r.pos)
else: internalError(info, "decodeLoc " & r.s[r.pos]) else: internalError(info, "decodeLoc " & r.s[r.pos])
proc decodeType(r: PRodReader, info: TLineInfo): PType = proc decodeType(r: PRodReader, info: TLineInfo): PType =
result = nil result = nil
if r.s[r.pos] == '[': if r.s[r.pos] == '[':
inc(r.pos) inc(r.pos)
if r.s[r.pos] == ']': if r.s[r.pos] == ']':
inc(r.pos) inc(r.pos)
return # nil type return # nil type
new(result) new(result)
result.kind = TTypeKind(decodeVInt(r.s, r.pos)) result.kind = TTypeKind(decodeVInt(r.s, r.pos))
if r.s[r.pos] == '+': if r.s[r.pos] == '+':
inc(r.pos) inc(r.pos)
result.id = decodeVInt(r.s, r.pos) result.id = decodeVInt(r.s, r.pos)
setId(result.id) setId(result.id)
if debugIds: registerID(result) if debugIds: registerID(result)
else: else:
internalError(info, "decodeType: no id") internalError(info, "decodeType: no id")
# here this also avoids endless recursion for recursive type # here this also avoids endless recursion for recursive type
idTablePut(gTypeTable, result, result) idTablePut(gTypeTable, result, result)
if r.s[r.pos] == '(': result.n = decodeNode(r, unknownLineInfo()) if r.s[r.pos] == '(': result.n = decodeNode(r, unknownLineInfo())
if r.s[r.pos] == '$': if r.s[r.pos] == '$':
inc(r.pos) inc(r.pos)
result.flags = cast[TTypeFlags](int32(decodeVInt(r.s, r.pos))) result.flags = cast[TTypeFlags](int32(decodeVInt(r.s, r.pos)))
if r.s[r.pos] == '?': if r.s[r.pos] == '?':
inc(r.pos) inc(r.pos)
result.callConv = TCallingConvention(decodeVInt(r.s, r.pos)) result.callConv = TCallingConvention(decodeVInt(r.s, r.pos))
if r.s[r.pos] == '*': if r.s[r.pos] == '*':
inc(r.pos) inc(r.pos)
result.owner = rrGetSym(r, decodeVInt(r.s, r.pos), info) result.owner = rrGetSym(r, decodeVInt(r.s, r.pos), info)
if r.s[r.pos] == '&': if r.s[r.pos] == '&':
inc(r.pos) inc(r.pos)
result.sym = rrGetSym(r, decodeVInt(r.s, r.pos), info) result.sym = rrGetSym(r, decodeVInt(r.s, r.pos), info)
if r.s[r.pos] == '/': if r.s[r.pos] == '/':
inc(r.pos) inc(r.pos)
result.size = decodeVInt(r.s, r.pos) result.size = decodeVInt(r.s, r.pos)
else: else:
result.size = - 1 result.size = - 1
if r.s[r.pos] == '=': if r.s[r.pos] == '=':
inc(r.pos) inc(r.pos)
result.align = decodeVInt(r.s, r.pos).int16 result.align = decodeVInt(r.s, r.pos).int16
else: else:
result.align = 2 result.align = 2
decodeLoc(r, result.loc, info) decodeLoc(r, result.loc, info)
while r.s[r.pos] == '^': while r.s[r.pos] == '^':
inc(r.pos) inc(r.pos)
if r.s[r.pos] == '(': if r.s[r.pos] == '(':
inc(r.pos) inc(r.pos)
if r.s[r.pos] == ')': inc(r.pos) if r.s[r.pos] == ')': inc(r.pos)
else: internalError(info, "decodeType ^(" & r.s[r.pos]) else: internalError(info, "decodeType ^(" & r.s[r.pos])
rawAddSon(result, nil) rawAddSon(result, nil)
else: else:
var d = decodeVInt(r.s, r.pos) var d = decodeVInt(r.s, r.pos)
rawAddSon(result, rrGetType(r, d, info)) rawAddSon(result, rrGetType(r, d, info))
proc decodeLib(r: PRodReader, info: TLineInfo): PLib = proc decodeLib(r: PRodReader, info: TLineInfo): PLib =
result = nil result = nil
if r.s[r.pos] == '|': if r.s[r.pos] == '|':
new(result) new(result)
inc(r.pos) inc(r.pos)
result.kind = TLibKind(decodeVInt(r.s, r.pos)) result.kind = TLibKind(decodeVInt(r.s, r.pos))
@ -349,31 +349,31 @@ proc decodeLib(r: PRodReader, info: TLineInfo): PLib =
inc(r.pos) inc(r.pos)
result.path = decodeNode(r, info) result.path = decodeNode(r, info)
proc decodeSym(r: PRodReader, info: TLineInfo): PSym = proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
var var
id: int id: int
ident: PIdent ident: PIdent
result = nil result = nil
if r.s[r.pos] == '{': if r.s[r.pos] == '{':
inc(r.pos) inc(r.pos)
if r.s[r.pos] == '}': if r.s[r.pos] == '}':
inc(r.pos) inc(r.pos)
return # nil sym return # nil sym
var k = TSymKind(decodeVInt(r.s, r.pos)) var k = TSymKind(decodeVInt(r.s, r.pos))
if r.s[r.pos] == '+': if r.s[r.pos] == '+':
inc(r.pos) inc(r.pos)
id = decodeVInt(r.s, r.pos) id = decodeVInt(r.s, r.pos)
setId(id) setId(id)
else: else:
internalError(info, "decodeSym: no id") internalError(info, "decodeSym: no id")
if r.s[r.pos] == '&': if r.s[r.pos] == '&':
inc(r.pos) inc(r.pos)
ident = getIdent(decodeStr(r.s, r.pos)) ident = getIdent(decodeStr(r.s, r.pos))
else: else:
internalError(info, "decodeSym: no ident") internalError(info, "decodeSym: no ident")
#echo "decoding: {", ident.s #echo "decoding: {", ident.s
result = PSym(idTableGet(r.syms, id)) result = PSym(idTableGet(r.syms, id))
if result == nil: if result == nil:
new(result) new(result)
result.id = id result.id = id
idTablePut(r.syms, result, result) idTablePut(r.syms, result, result)
@ -388,35 +388,35 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
result.id = id result.id = id
result.kind = k result.kind = k
result.name = ident # read the rest of the symbol description: result.name = ident # read the rest of the symbol description:
if r.s[r.pos] == '^': if r.s[r.pos] == '^':
inc(r.pos) inc(r.pos)
result.typ = rrGetType(r, decodeVInt(r.s, r.pos), info) result.typ = rrGetType(r, decodeVInt(r.s, r.pos), info)
decodeLineInfo(r, result.info) decodeLineInfo(r, result.info)
if r.s[r.pos] == '*': if r.s[r.pos] == '*':
inc(r.pos) inc(r.pos)
result.owner = rrGetSym(r, decodeVInt(r.s, r.pos), result.info) result.owner = rrGetSym(r, decodeVInt(r.s, r.pos), result.info)
if r.s[r.pos] == '$': if r.s[r.pos] == '$':
inc(r.pos) inc(r.pos)
result.flags = cast[TSymFlags](int32(decodeVInt(r.s, r.pos))) result.flags = cast[TSymFlags](int32(decodeVInt(r.s, r.pos)))
if r.s[r.pos] == '@': if r.s[r.pos] == '@':
inc(r.pos) inc(r.pos)
result.magic = TMagic(decodeVInt(r.s, r.pos)) result.magic = TMagic(decodeVInt(r.s, r.pos))
if r.s[r.pos] == '!': if r.s[r.pos] == '!':
inc(r.pos) inc(r.pos)
result.options = cast[TOptions](int32(decodeVInt(r.s, r.pos))) result.options = cast[TOptions](int32(decodeVInt(r.s, r.pos)))
else: else:
result.options = r.options result.options = r.options
if r.s[r.pos] == '%': if r.s[r.pos] == '%':
inc(r.pos) inc(r.pos)
result.position = decodeVInt(r.s, r.pos) result.position = decodeVInt(r.s, r.pos)
elif result.kind notin routineKinds + {skModule}: elif result.kind notin routineKinds + {skModule}:
result.position = 0 result.position = 0
# this may have been misused as reader index! But we still # this may have been misused as reader index! But we still
# need it for routines as the body is loaded lazily. # need it for routines as the body is loaded lazily.
if r.s[r.pos] == '`': if r.s[r.pos] == '`':
inc(r.pos) inc(r.pos)
result.offset = decodeVInt(r.s, r.pos) result.offset = decodeVInt(r.s, r.pos)
else: else:
result.offset = - 1 result.offset = - 1
decodeLoc(r, result.loc, result.info) decodeLoc(r, result.loc, result.info)
result.annex = decodeLib(r, info) result.annex = decodeLib(r, info)
@ -433,35 +433,35 @@ proc decodeSym(r: PRodReader, info: TLineInfo): PSym =
result.ast = decodeNode(r, result.info) result.ast = decodeNode(r, result.info)
#echo "decoded: ", ident.s, "}" #echo "decoded: ", ident.s, "}"
proc skipSection(r: PRodReader) = proc skipSection(r: PRodReader) =
if r.s[r.pos] == ':': if r.s[r.pos] == ':':
while r.s[r.pos] > '\x0A': inc(r.pos) while r.s[r.pos] > '\x0A': inc(r.pos)
elif r.s[r.pos] == '(': elif r.s[r.pos] == '(':
var c = 0 # count () pairs var c = 0 # count () pairs
inc(r.pos) inc(r.pos)
while true: while true:
case r.s[r.pos] case r.s[r.pos]
of '\x0A': inc(r.line) of '\x0A': inc(r.line)
of '(': inc(c) of '(': inc(c)
of ')': of ')':
if c == 0: if c == 0:
inc(r.pos) inc(r.pos)
break break
elif c > 0: elif c > 0:
dec(c) dec(c)
of '\0': break # end of file of '\0': break # end of file
else: discard else: discard
inc(r.pos) inc(r.pos)
else: else:
internalError("skipSection " & $r.line) internalError("skipSection " & $r.line)
proc rdWord(r: PRodReader): string = proc rdWord(r: PRodReader): string =
result = "" result = ""
while r.s[r.pos] in {'A'..'Z', '_', 'a'..'z', '0'..'9'}: while r.s[r.pos] in {'A'..'Z', '_', 'a'..'z', '0'..'9'}:
add(result, r.s[r.pos]) add(result, r.s[r.pos])
inc(r.pos) inc(r.pos)
proc newStub(r: PRodReader, name: string, id: int): PSym = proc newStub(r: PRodReader, name: string, id: int): PSym =
new(result) new(result)
result.kind = skStub result.kind = skStub
result.id = id result.id = id
@ -469,11 +469,11 @@ proc newStub(r: PRodReader, name: string, id: int): PSym =
result.position = r.readerIndex result.position = r.readerIndex
setId(id) #MessageOut(result.name.s); setId(id) #MessageOut(result.name.s);
if debugIds: registerID(result) if debugIds: registerID(result)
proc processInterf(r: PRodReader, module: PSym) = proc processInterf(r: PRodReader, module: PSym) =
if r.interfIdx == 0: internalError("processInterf") if r.interfIdx == 0: internalError("processInterf")
r.pos = r.interfIdx r.pos = r.interfIdx
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
var w = decodeStr(r.s, r.pos) var w = decodeStr(r.s, r.pos)
inc(r.pos) inc(r.pos)
var key = decodeVInt(r.s, r.pos) var key = decodeVInt(r.s, r.pos)
@ -483,28 +483,28 @@ proc processInterf(r: PRodReader, module: PSym) =
strTableAdd(module.tab, s) strTableAdd(module.tab, s)
idTablePut(r.syms, s, s) idTablePut(r.syms, s, s)
proc processCompilerProcs(r: PRodReader, module: PSym) = proc processCompilerProcs(r: PRodReader, module: PSym) =
if r.compilerProcsIdx == 0: internalError("processCompilerProcs") if r.compilerProcsIdx == 0: internalError("processCompilerProcs")
r.pos = r.compilerProcsIdx r.pos = r.compilerProcsIdx
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
var w = decodeStr(r.s, r.pos) var w = decodeStr(r.s, r.pos)
inc(r.pos) inc(r.pos)
var key = decodeVInt(r.s, r.pos) var key = decodeVInt(r.s, r.pos)
inc(r.pos) # #10 inc(r.pos) # #10
var s = PSym(idTableGet(r.syms, key)) var s = PSym(idTableGet(r.syms, key))
if s == nil: if s == nil:
s = newStub(r, w, key) s = newStub(r, w, key)
s.owner = module s.owner = module
idTablePut(r.syms, s, s) idTablePut(r.syms, s, s)
strTableAdd(rodCompilerprocs, s) strTableAdd(rodCompilerprocs, s)
proc processIndex(r: PRodReader; idx: var TIndex; outf: File = nil) = proc processIndex(r: PRodReader; idx: var TIndex; outf: File = nil) =
var key, val, tmp: int var key, val, tmp: int
inc(r.pos, 2) # skip "(\10" inc(r.pos, 2) # skip "(\10"
inc(r.line) inc(r.line)
while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'): while (r.s[r.pos] > '\x0A') and (r.s[r.pos] != ')'):
tmp = decodeVInt(r.s, r.pos) tmp = decodeVInt(r.s, r.pos)
if r.s[r.pos] == ' ': if r.s[r.pos] == ' ':
inc(r.pos) inc(r.pos)
key = idx.lastIdxKey + tmp key = idx.lastIdxKey + tmp
val = decodeVInt(r.s, r.pos) + idx.lastIdxVal val = decodeVInt(r.s, r.pos) + idx.lastIdxVal
@ -516,11 +516,11 @@ proc processIndex(r: PRodReader; idx: var TIndex; outf: File = nil) =
idx.lastIdxKey = key idx.lastIdxKey = key
idx.lastIdxVal = val idx.lastIdxVal = val
setId(key) # ensure that this id will not be used setId(key) # ensure that this id will not be used
if r.s[r.pos] == '\x0A': if r.s[r.pos] == '\x0A':
inc(r.pos) inc(r.pos)
inc(r.line) inc(r.line)
if r.s[r.pos] == ')': inc(r.pos) if r.s[r.pos] == ')': inc(r.pos)
proc cmdChangeTriggersRecompilation(old, new: TCommands): bool = proc cmdChangeTriggersRecompilation(old, new: TCommands): bool =
if old == new: return false if old == new: return false
# we use a 'case' statement without 'else' so that addition of a # we use a 'case' statement without 'else' so that addition of a
@ -532,34 +532,34 @@ proc cmdChangeTriggersRecompilation(old, new: TCommands): bool =
cmdInteractive}: cmdInteractive}:
return false return false
of cmdNone, cmdDoc, cmdInterpret, cmdPretty, cmdGenDepend, cmdDump, of cmdNone, cmdDoc, cmdInterpret, cmdPretty, cmdGenDepend, cmdDump,
cmdCheck, cmdParse, cmdScan, cmdIdeTools, cmdDef, cmdCheck, cmdParse, cmdScan, cmdIdeTools, cmdDef,
cmdRst2html, cmdRst2tex, cmdInteractive, cmdRun: cmdRst2html, cmdRst2tex, cmdInteractive, cmdRun:
discard discard
# else: trigger recompilation: # else: trigger recompilation:
result = true result = true
proc processRodFile(r: PRodReader, crc: SecureHash) = proc processRodFile(r: PRodReader, crc: SecureHash) =
var var
w: string w: string
d: int d: int
var inclCrc: SecureHash var inclCrc: SecureHash
while r.s[r.pos] != '\0': while r.s[r.pos] != '\0':
var section = rdWord(r) var section = rdWord(r)
if r.reason != rrNone: if r.reason != rrNone:
break # no need to process this file further break # no need to process this file further
case section case section
of "CRC": of "CRC":
inc(r.pos) # skip ':' inc(r.pos) # skip ':'
if crc != parseSecureHash(decodeStr(r.s, r.pos)): if crc != parseSecureHash(decodeStr(r.s, r.pos)):
r.reason = rrCrcChange r.reason = rrCrcChange
of "ID": of "ID":
inc(r.pos) # skip ':' inc(r.pos) # skip ':'
r.moduleID = decodeVInt(r.s, r.pos) r.moduleID = decodeVInt(r.s, r.pos)
setId(r.moduleID) setId(r.moduleID)
of "ORIGFILE": of "ORIGFILE":
inc(r.pos) inc(r.pos)
r.origFile = decodeStr(r.s, r.pos) r.origFile = decodeStr(r.s, r.pos)
of "OPTIONS": of "OPTIONS":
inc(r.pos) # skip ':' inc(r.pos) # skip ':'
r.options = cast[TOptions](int32(decodeVInt(r.s, r.pos))) r.options = cast[TOptions](int32(decodeVInt(r.s, r.pos)))
if options.gOptions != r.options: r.reason = rrOptions if options.gOptions != r.options: r.reason = rrOptions
@ -574,14 +574,14 @@ proc processRodFile(r: PRodReader, crc: SecureHash) =
of "DEFINES": of "DEFINES":
inc(r.pos) # skip ':' inc(r.pos) # skip ':'
d = 0 d = 0
while r.s[r.pos] > '\x0A': while r.s[r.pos] > '\x0A':
w = decodeStr(r.s, r.pos) w = decodeStr(r.s, r.pos)
inc(d) inc(d)
if not condsyms.isDefined(getIdent(w)): if not condsyms.isDefined(getIdent(w)):
r.reason = rrDefines #MessageOut('not defined, but should: ' + w); r.reason = rrDefines #MessageOut('not defined, but should: ' + w);
if r.s[r.pos] == ' ': inc(r.pos) if r.s[r.pos] == ' ': inc(r.pos)
if (d != countDefinedSymbols()): r.reason = rrDefines if (d != countDefinedSymbols()): r.reason = rrDefines
of "FILES": of "FILES":
inc(r.pos, 2) # skip "(\10" inc(r.pos, 2) # skip "(\10"
inc(r.line) inc(r.line)
while r.s[r.pos] != ')': while r.s[r.pos] != ')':
@ -592,17 +592,17 @@ proc processRodFile(r: PRodReader, crc: SecureHash) =
inc(r.pos) # skip #10 inc(r.pos) # skip #10
inc(r.line) inc(r.line)
if r.s[r.pos] == ')': inc(r.pos) if r.s[r.pos] == ')': inc(r.pos)
of "INCLUDES": of "INCLUDES":
inc(r.pos, 2) # skip "(\10" inc(r.pos, 2) # skip "(\10"
inc(r.line) inc(r.line)
while r.s[r.pos] != ')': while r.s[r.pos] != ')':
w = r.files[decodeVInt(r.s, r.pos)].toFullPath w = r.files[decodeVInt(r.s, r.pos)].toFullPath
inc(r.pos) # skip ' ' inc(r.pos) # skip ' '
inclCrc = parseSecureHash(decodeStr(r.s, r.pos)) inclCrc = parseSecureHash(decodeStr(r.s, r.pos))
if r.reason == rrNone: if r.reason == rrNone:
if not existsFile(w) or (inclCrc != secureHashFile(w)): if not existsFile(w) or (inclCrc != secureHashFile(w)):
r.reason = rrInclDeps r.reason = rrInclDeps
if r.s[r.pos] == '\x0A': if r.s[r.pos] == '\x0A':
inc(r.pos) inc(r.pos)
inc(r.line) inc(r.line)
if r.s[r.pos] == ')': inc(r.pos) if r.s[r.pos] == ')': inc(r.pos)
@ -611,28 +611,28 @@ proc processRodFile(r: PRodReader, crc: SecureHash) =
while r.s[r.pos] > '\x0A': while r.s[r.pos] > '\x0A':
r.modDeps.add(r.files[int32(decodeVInt(r.s, r.pos))]) r.modDeps.add(r.files[int32(decodeVInt(r.s, r.pos))])
if r.s[r.pos] == ' ': inc(r.pos) if r.s[r.pos] == ' ': inc(r.pos)
of "INTERF": of "INTERF":
r.interfIdx = r.pos + 2 r.interfIdx = r.pos + 2
skipSection(r) skipSection(r)
of "COMPILERPROCS": of "COMPILERPROCS":
r.compilerProcsIdx = r.pos + 2 r.compilerProcsIdx = r.pos + 2
skipSection(r) skipSection(r)
of "INDEX": of "INDEX":
processIndex(r, r.index) processIndex(r, r.index)
of "IMPORTS": of "IMPORTS":
processIndex(r, r.imports) processIndex(r, r.imports)
of "CONVERTERS": of "CONVERTERS":
r.convertersIdx = r.pos + 1 r.convertersIdx = r.pos + 1
skipSection(r) skipSection(r)
of "METHODS": of "METHODS":
r.methodsIdx = r.pos + 1 r.methodsIdx = r.pos + 1
skipSection(r) skipSection(r)
of "DATA": of "DATA":
r.dataIdx = r.pos + 2 # "(\10" r.dataIdx = r.pos + 2 # "(\10"
# We do not read the DATA section here! We read the needed objects on # We do not read the DATA section here! We read the needed objects on
# demand. And the DATA section comes last in the file, so we stop here: # demand. And the DATA section comes last in the file, so we stop here:
break break
of "INIT": of "INIT":
r.initIdx = r.pos + 2 # "(\10" r.initIdx = r.pos + 2 # "(\10"
skipSection(r) skipSection(r)
else: else:
@ -641,7 +641,7 @@ proc processRodFile(r: PRodReader, crc: SecureHash) =
#MsgWriteln("skipping section: " & section & #MsgWriteln("skipping section: " & section &
# " at " & $r.line & " in " & r.filename) # " at " & $r.line & " 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)
inc(r.line) inc(r.line)
@ -652,7 +652,7 @@ proc startsWith(buf: cstring, token: string, pos = 0): bool =
result = s == token.len result = s == token.len
proc newRodReader(modfilename: string, crc: SecureHash, proc newRodReader(modfilename: string, crc: SecureHash,
readerIndex: int): PRodReader = readerIndex: int): PRodReader =
new(result) new(result)
try: try:
result.memfile = memfiles.open(modfilename) result.memfile = memfiles.open(modfilename)
@ -671,7 +671,7 @@ proc newRodReader(modfilename: string, crc: SecureHash,
# we terminate the file explicitly with ``\0``, so the cast to `cstring` # we terminate the file explicitly with ``\0``, so the cast to `cstring`
# is safe: # is safe:
r.s = cast[cstring](r.memfile.mem) r.s = cast[cstring](r.memfile.mem)
if startsWith(r.s, "NIM:"): if startsWith(r.s, "NIM:"):
initIiTable(r.index.tab) initIiTable(r.index.tab)
initIiTable(r.imports.tab) # looks like a ROD file initIiTable(r.imports.tab) # looks like a ROD file
inc(r.pos, 4) inc(r.pos, 4)
@ -680,16 +680,16 @@ proc newRodReader(modfilename: string, crc: SecureHash,
add(version, r.s[r.pos]) add(version, r.s[r.pos])
inc(r.pos) inc(r.pos)
if r.s[r.pos] == '\x0A': inc(r.pos) if r.s[r.pos] == '\x0A': inc(r.pos)
if version != RodFileVersion: if version != RodFileVersion:
# since ROD files are only for caching, no backwards compatibility is # since ROD files are only for caching, no backwards compatibility is
# needed # needed
result = nil result = nil
else: else:
result = nil result = nil
proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType = proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType =
result = PType(idTableGet(gTypeTable, id)) result = PType(idTableGet(gTypeTable, id))
if result == nil: if result == nil:
# load the type: # load the type:
var oldPos = r.pos var oldPos = r.pos
var d = iiTableGet(r.index.tab, id) var d = iiTableGet(r.index.tab, id)
@ -698,8 +698,8 @@ proc rrGetType(r: PRodReader, id: int, info: TLineInfo): PType =
result = decodeType(r, info) result = decodeType(r, info)
r.pos = oldPos r.pos = oldPos
type type
TFileModuleRec{.final.} = object TFileModuleRec{.final.} = object
filename*: string filename*: string
reason*: TReasonForRecompile reason*: TReasonForRecompile
rd*: PRodReader rd*: PRodReader
@ -710,7 +710,7 @@ type
var gMods*: TFileModuleMap = @[] var gMods*: TFileModuleMap = @[]
proc decodeSymSafePos(rd: PRodReader, offset: int, info: TLineInfo): PSym = proc decodeSymSafePos(rd: PRodReader, offset: int, info: TLineInfo): PSym =
# all compiled modules # all compiled modules
if rd.dataIdx == 0: internalError(info, "dataIdx == 0") if rd.dataIdx == 0: internalError(info, "dataIdx == 0")
var oldPos = rd.pos var oldPos = rd.pos
@ -719,9 +719,9 @@ proc decodeSymSafePos(rd: PRodReader, offset: int, info: TLineInfo): PSym =
rd.pos = oldPos rd.pos = oldPos
proc findSomeWhere(id: int) = proc findSomeWhere(id: int) =
for i in countup(0, high(gMods)): for i in countup(0, high(gMods)):
var rd = gMods[i].rd var rd = gMods[i].rd
if rd != nil: if rd != nil:
var d = iiTableGet(rd.index.tab, id) var d = iiTableGet(rd.index.tab, id)
if d != InvalidKey: if d != InvalidKey:
echo "found id ", id, " in ", gMods[i].filename echo "found id ", id, " in ", gMods[i].filename
@ -736,12 +736,12 @@ proc getReader(moduleId: int): PRodReader =
if result != nil and result.moduleID == moduleId: return result if result != nil and result.moduleID == moduleId: return result
return nil return nil
proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym = proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
result = PSym(idTableGet(r.syms, id)) result = PSym(idTableGet(r.syms, id))
if result == nil: if result == nil:
# load the symbol: # load the symbol:
var d = iiTableGet(r.index.tab, id) var d = iiTableGet(r.index.tab, id)
if d == InvalidKey: if d == InvalidKey:
# import from other module: # import from other module:
var moduleID = iiTableGet(r.imports.tab, id) var moduleID = iiTableGet(r.imports.tab, id)
if moduleID < 0: if moduleID < 0:
@ -750,24 +750,24 @@ proc rrGetSym(r: PRodReader, id: int, info: TLineInfo): PSym =
internalError(info, "missing from both indexes: +" & x) internalError(info, "missing from both indexes: +" & x)
var rd = getReader(moduleID) var rd = getReader(moduleID)
d = iiTableGet(rd.index.tab, id) d = iiTableGet(rd.index.tab, id)
if d != InvalidKey: if d != InvalidKey:
result = decodeSymSafePos(rd, d, info) result = decodeSymSafePos(rd, d, info)
else: else:
var x = "" var x = ""
encodeVInt(id, x) encodeVInt(id, x)
when false: findSomeWhere(id) when false: findSomeWhere(id)
internalError(info, "rrGetSym: no reader found: +" & x) internalError(info, "rrGetSym: no reader found: +" & x)
else: else:
# own symbol: # own symbol:
result = decodeSymSafePos(r, d, info) result = decodeSymSafePos(r, d, info)
if result != nil and result.kind == skStub: rawLoadStub(result) if result != nil and result.kind == skStub: rawLoadStub(result)
proc loadInitSection(r: PRodReader): PNode = proc loadInitSection(r: PRodReader): PNode =
if r.initIdx == 0 or r.dataIdx == 0: internalError("loadInitSection") if r.initIdx == 0 or r.dataIdx == 0: internalError("loadInitSection")
var oldPos = r.pos var oldPos = r.pos
r.pos = r.initIdx r.pos = r.initIdx
result = newNode(nkStmtList) result = newNode(nkStmtList)
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')': while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
var d = decodeVInt(r.s, r.pos) var d = decodeVInt(r.s, r.pos)
inc(r.pos) # #10 inc(r.pos) # #10
var p = r.pos var p = r.pos
@ -776,13 +776,13 @@ proc loadInitSection(r: PRodReader): PNode =
r.pos = p r.pos = p
r.pos = oldPos r.pos = oldPos
proc loadConverters(r: PRodReader) = proc loadConverters(r: PRodReader) =
# We have to ensure that no exported converter is a stub anymore, and the # We have to ensure that no exported converter is a stub anymore, and the
# import mechanism takes care of the rest. # import mechanism takes care of the rest.
if r.convertersIdx == 0 or r.dataIdx == 0: if r.convertersIdx == 0 or r.dataIdx == 0:
internalError("importConverters") internalError("importConverters")
r.pos = r.convertersIdx r.pos = r.convertersIdx
while r.s[r.pos] > '\x0A': while r.s[r.pos] > '\x0A':
var d = decodeVInt(r.s, r.pos) var d = decodeVInt(r.s, r.pos)
discard rrGetSym(r, d, unknownLineInfo()) discard rrGetSym(r, d, unknownLineInfo())
if r.s[r.pos] == ' ': inc(r.pos) if r.s[r.pos] == ' ': inc(r.pos)
@ -801,7 +801,7 @@ proc getCRC*(fileIdx: int32): SecureHash =
if gMods[fileIdx].crcDone: if gMods[fileIdx].crcDone:
return gMods[fileIdx].crc return gMods[fileIdx].crc
result = secureHashFile(fileIdx.toFilename) result = secureHashFile(fileIdx.toFilename)
gMods[fileIdx].crc = result gMods[fileIdx].crc = result
@ -811,7 +811,7 @@ template growCache*(cache, pos) =
proc checkDep(fileIdx: int32): TReasonForRecompile = proc checkDep(fileIdx: int32): TReasonForRecompile =
assert fileIdx != InvalidFileIDX assert fileIdx != InvalidFileIDX
growCache gMods, fileIdx growCache gMods, fileIdx
if gMods[fileIdx].reason != rrEmpty: if gMods[fileIdx].reason != rrEmpty:
# reason has already been computed for this module: # reason has already been computed for this module:
return gMods[fileIdx].reason return gMods[fileIdx].reason
let filename = fileIdx.toFilename let filename = fileIdx.toFilename
@ -821,12 +821,12 @@ proc checkDep(fileIdx: int32): TReasonForRecompile =
var r: PRodReader = nil var r: PRodReader = nil
var rodfile = toGeneratedFile(filename.withPackageName, RodExt) var rodfile = toGeneratedFile(filename.withPackageName, RodExt)
r = newRodReader(rodfile, crc, fileIdx) r = newRodReader(rodfile, crc, fileIdx)
if r == nil: if r == nil:
result = (if existsFile(rodfile): rrRodInvalid else: rrRodDoesNotExist) result = (if existsFile(rodfile): rrRodInvalid else: rrRodDoesNotExist)
else: else:
processRodFile(r, crc) processRodFile(r, crc)
result = r.reason result = r.reason
if result == rrNone: if result == rrNone:
# check modules it depends on # check modules it depends on
# NOTE: we need to process the entire module graph so that no ID will # NOTE: we need to process the entire module graph so that no ID will
# be used twice! However, compilation speed does not suffer much from # be used twice! However, compilation speed does not suffer much from
@ -846,10 +846,10 @@ proc checkDep(fileIdx: int32): TReasonForRecompile =
r = nil r = nil
gMods[fileIdx].rd = r gMods[fileIdx].rd = r
gMods[fileIdx].reason = result # now we know better gMods[fileIdx].reason = result # now we know better
proc handleSymbolFile(module: PSym): PRodReader = proc handleSymbolFile(module: PSym): PRodReader =
let fileIdx = module.fileIdx let fileIdx = module.fileIdx
if optSymbolFiles notin gGlobalOptions: if optSymbolFiles notin gGlobalOptions:
module.id = getID() module.id = getID()
return nil return nil
idgen.loadMaxIds(options.gProjectPath / options.gProjectName) idgen.loadMaxIds(options.gProjectPath / options.gProjectName)
@ -857,7 +857,7 @@ proc handleSymbolFile(module: PSym): PRodReader =
discard checkDep(fileIdx) discard checkDep(fileIdx)
if gMods[fileIdx].reason == rrEmpty: internalError("handleSymbolFile") if gMods[fileIdx].reason == rrEmpty: internalError("handleSymbolFile")
result = gMods[fileIdx].rd result = gMods[fileIdx].rd
if result != nil: if result != nil:
module.id = result.moduleID module.id = result.moduleID
idTablePut(result.syms, module, module) idTablePut(result.syms, module, module)
processInterf(result, module) processInterf(result, module)
@ -878,13 +878,13 @@ proc rawLoadStub(s: PSym) =
#echo "rs: ", toHex(cast[int](rs.position), int.sizeof * 2), #echo "rs: ", toHex(cast[int](rs.position), int.sizeof * 2),
# "\ns: ", toHex(cast[int](s.position), int.sizeof * 2) # "\ns: ", toHex(cast[int](s.position), int.sizeof * 2)
internalError(rs.info, "loadStub: wrong symbol") internalError(rs.info, "loadStub: wrong symbol")
elif rs.id != theId: elif rs.id != theId:
internalError(rs.info, "loadStub: wrong ID") internalError(rs.info, "loadStub: wrong ID")
#MessageOut('loaded stub: ' + s.name.s); #MessageOut('loaded stub: ' + s.name.s);
proc loadStub*(s: PSym) = proc loadStub*(s: PSym) =
## loads the stub symbol `s`. ## loads the stub symbol `s`.
# deactivate the GC here because we do a deep recursion and generate no # deactivate the GC here because we do a deep recursion and generate no
# garbage when restoring parts of the object graph anyway. # garbage when restoring parts of the object graph anyway.
# Since we die with internal errors if this fails, no try-finally is # Since we die with internal errors if this fails, no try-finally is
@ -892,7 +892,7 @@ proc loadStub*(s: PSym) =
GC_disable() GC_disable()
rawLoadStub(s) rawLoadStub(s)
GC_enable() GC_enable()
proc getBody*(s: PSym): PNode = proc getBody*(s: PSym): PNode =
## retrieves the AST's body of `s`. If `s` has been loaded from a rod-file ## retrieves the AST's body of `s`. If `s` has been loaded from a rod-file
## it may perform an expensive reload operation. Otherwise it's a simple ## it may perform an expensive reload operation. Otherwise it's a simple
@ -908,7 +908,7 @@ proc getBody*(s: PSym): PNode =
r.pos = oldPos r.pos = oldPos
s.ast.sons[bodyPos] = result s.ast.sons[bodyPos] = result
s.offset = 0 s.offset = 0
initIdTable(gTypeTable) initIdTable(gTypeTable)
initStrTable(rodCompilerprocs) initStrTable(rodCompilerprocs)
@ -921,16 +921,16 @@ proc writeNode(f: File; n: PNode) =
f.write('^') f.write('^')
f.write(n.typ.id) f.write(n.typ.id)
case n.kind case n.kind
of nkCharLit..nkInt64Lit: of nkCharLit..nkInt64Lit:
if n.intVal != 0: if n.intVal != 0:
f.write('!') f.write('!')
f.write(n.intVal) f.write(n.intVal)
of nkFloatLit..nkFloat64Lit: of nkFloatLit..nkFloat64Lit:
if n.floatVal != 0.0: if n.floatVal != 0.0:
f.write('!') f.write('!')
f.write($n.floatVal) f.write($n.floatVal)
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
if n.strVal != "": if n.strVal != "":
f.write('!') f.write('!')
f.write(n.strVal.escape) f.write(n.strVal.escape)
of nkIdent: of nkIdent:
@ -940,7 +940,7 @@ proc writeNode(f: File; n: PNode) =
f.write('!') f.write('!')
f.write(n.sym.id) f.write(n.sym.id)
else: else:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
writeNode(f, n.sons[i]) writeNode(f, n.sons[i])
f.write(")") f.write(")")
@ -966,10 +966,10 @@ proc writeSym(f: File; s: PSym) =
if s.magic != mNone: if s.magic != mNone:
f.write('@') f.write('@')
f.write($s.magic) f.write($s.magic)
if s.options != gOptions: if s.options != gOptions:
f.write('!') f.write('!')
f.write($s.options) f.write($s.options)
if s.position != 0: if s.position != 0:
f.write('%') f.write('%')
f.write($s.position) f.write($s.position)
if s.offset != -1: if s.offset != -1:
@ -990,12 +990,12 @@ proc writeType(f: File; t: PType) =
f.write($t.kind) f.write($t.kind)
f.write('+') f.write('+')
f.write($t.id) f.write($t.id)
if t.n != nil: if t.n != nil:
f.writeNode(t.n) f.writeNode(t.n)
if t.flags != {}: if t.flags != {}:
f.write('$') f.write('$')
f.write($t.flags) f.write($t.flags)
if t.callConv != low(t.callConv): if t.callConv != low(t.callConv):
f.write('?') f.write('?')
f.write($t.callConv) f.write($t.callConv)
if t.owner != nil: if t.owner != nil:
@ -1010,11 +1010,11 @@ proc writeType(f: File; t: PType) =
if t.align != 2: if t.align != 2:
f.write('=') f.write('=')
f.write($t.align) f.write($t.align)
for i in countup(0, sonsLen(t) - 1): for i in countup(0, sonsLen(t) - 1):
if t.sons[i] == nil: if t.sons[i] == nil:
f.write("^()") f.write("^()")
else: else:
f.write('^') f.write('^')
f.write($t.sons[i].id) f.write($t.sons[i].id)
f.write("]\n") f.write("]\n")
@ -1031,28 +1031,28 @@ proc viewFile(rodfile: string) =
case section case section
of "CRC": of "CRC":
inc(r.pos) # skip ':' inc(r.pos) # skip ':'
outf.writeln("CRC:", $decodeVInt(r.s, r.pos)) outf.writeLine("CRC:", $decodeVInt(r.s, r.pos))
of "ID": of "ID":
inc(r.pos) # skip ':' inc(r.pos) # skip ':'
r.moduleID = decodeVInt(r.s, r.pos) r.moduleID = decodeVInt(r.s, r.pos)
setId(r.moduleID) setId(r.moduleID)
outf.writeln("ID:", $r.moduleID) outf.writeLine("ID:", $r.moduleID)
of "ORIGFILE": of "ORIGFILE":
inc(r.pos) inc(r.pos)
r.origFile = decodeStr(r.s, r.pos) r.origFile = decodeStr(r.s, r.pos)
outf.writeln("ORIGFILE:", r.origFile) outf.writeLine("ORIGFILE:", r.origFile)
of "OPTIONS": of "OPTIONS":
inc(r.pos) # skip ':' inc(r.pos) # skip ':'
r.options = cast[TOptions](int32(decodeVInt(r.s, r.pos))) r.options = cast[TOptions](int32(decodeVInt(r.s, r.pos)))
outf.writeln("OPTIONS:", $r.options) outf.writeLine("OPTIONS:", $r.options)
of "GOPTIONS": of "GOPTIONS":
inc(r.pos) # skip ':' inc(r.pos) # skip ':'
let dep = cast[TGlobalOptions](int32(decodeVInt(r.s, r.pos))) let dep = cast[TGlobalOptions](int32(decodeVInt(r.s, r.pos)))
outf.writeln("GOPTIONS:", $dep) outf.writeLine("GOPTIONS:", $dep)
of "CMD": of "CMD":
inc(r.pos) # skip ':' inc(r.pos) # skip ':'
let dep = cast[TCommands](int32(decodeVInt(r.s, r.pos))) let dep = cast[TCommands](int32(decodeVInt(r.s, r.pos)))
outf.writeln("CMD:", $dep) outf.writeLine("CMD:", $dep)
of "DEFINES": of "DEFINES":
inc(r.pos) # skip ':' inc(r.pos) # skip ':'
var d = 0 var d = 0
@ -1074,18 +1074,18 @@ proc viewFile(rodfile: string) =
r.files.add(finalPath.fileInfoIdx) r.files.add(finalPath.fileInfoIdx)
inc(r.pos) # skip #10 inc(r.pos) # skip #10
inc(r.line) inc(r.line)
outf.writeln finalPath outf.writeLine finalPath
if r.s[r.pos] == ')': inc(r.pos) if r.s[r.pos] == ')': inc(r.pos)
outf.write(")\n") outf.write(")\n")
of "INCLUDES": of "INCLUDES":
inc(r.pos, 2) # skip "(\10" inc(r.pos, 2) # skip "(\10"
inc(r.line) inc(r.line)
outf.write("INCLUDES(\n") outf.write("INCLUDES(\n")
while r.s[r.pos] != ')': while r.s[r.pos] != ')':
let w = r.files[decodeVInt(r.s, r.pos)] let w = r.files[decodeVInt(r.s, r.pos)]
inc(r.pos) # skip ' ' inc(r.pos) # skip ' '
let inclCrc = decodeVInt(r.s, r.pos) let inclCrc = decodeVInt(r.s, r.pos)
if r.s[r.pos] == '\x0A': if r.s[r.pos] == '\x0A':
inc(r.pos) inc(r.pos)
inc(r.line) inc(r.line)
outf.write(w, " ", inclCrc, "\n") outf.write(w, " ", inclCrc, "\n")
@ -1094,7 +1094,7 @@ proc viewFile(rodfile: string) =
of "DEPS": of "DEPS":
inc(r.pos) # skip ':' inc(r.pos) # skip ':'
outf.write("DEPS:") outf.write("DEPS:")
while r.s[r.pos] > '\x0A': while r.s[r.pos] > '\x0A':
let v = int32(decodeVInt(r.s, r.pos)) let v = int32(decodeVInt(r.s, r.pos))
r.modDeps.add(r.files[v]) r.modDeps.add(r.files[v])
if r.s[r.pos] == ' ': inc(r.pos) if r.s[r.pos] == ' ': inc(r.pos)
@ -1126,7 +1126,7 @@ proc viewFile(rodfile: string) =
if section == "METHODS": r.methodsIdx = r.pos if section == "METHODS": r.methodsIdx = r.pos
else: r.convertersIdx = r.pos else: r.convertersIdx = r.pos
outf.write(section, ":") outf.write(section, ":")
while r.s[r.pos] > '\x0A': while r.s[r.pos] > '\x0A':
let d = decodeVInt(r.s, r.pos) let d = decodeVInt(r.s, r.pos)
outf.write(" ", $d) outf.write(" ", $d)
if r.s[r.pos] == ' ': inc(r.pos) if r.s[r.pos] == ' ': inc(r.pos)
@ -1152,7 +1152,7 @@ proc viewFile(rodfile: string) =
outf.write("INIT(\n") outf.write("INIT(\n")
inc r.pos, 2 inc r.pos, 2
r.initIdx = r.pos r.initIdx = r.pos
while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')': while r.s[r.pos] > '\x0A' and r.s[r.pos] != ')':
let d = decodeVInt(r.s, r.pos) let d = decodeVInt(r.s, r.pos)
inc(r.pos) # #10 inc(r.pos) # #10
#let p = r.pos #let p = r.pos

View file

@ -218,12 +218,12 @@ proc cmpCandidates*(a, b: TCandidate): int =
result = complexDisambiguation(a.callee, b.callee) result = complexDisambiguation(a.callee, b.callee)
proc writeMatches*(c: TCandidate) = proc writeMatches*(c: TCandidate) =
writeln(stdout, "exact matches: " & $c.exactMatches) writeLine(stdout, "exact matches: " & $c.exactMatches)
writeln(stdout, "generic matches: " & $c.genericMatches) writeLine(stdout, "generic matches: " & $c.genericMatches)
writeln(stdout, "subtype matches: " & $c.subtypeMatches) writeLine(stdout, "subtype matches: " & $c.subtypeMatches)
writeln(stdout, "intconv matches: " & $c.intConvMatches) writeLine(stdout, "intconv matches: " & $c.intConvMatches)
writeln(stdout, "conv matches: " & $c.convMatches) writeLine(stdout, "conv matches: " & $c.convMatches)
writeln(stdout, "inheritance: " & $c.inheritancePenalty) writeLine(stdout, "inheritance: " & $c.inheritancePenalty)
proc argTypeToString(arg: PNode; prefer: TPreferedDesc): string = proc argTypeToString(arg: PNode; prefer: TPreferedDesc): string =
if arg.kind in nkSymChoices: if arg.kind in nkSymChoices:

View file

@ -222,13 +222,13 @@ Call with named arguments
Concrete syntax: Concrete syntax:
.. code-block:: nim .. code-block:: nim
writeln(file=stdout, "hallo") writeLine(file=stdout, "hallo")
AST: AST:
.. code-block:: nim .. code-block:: nim
nnkCall( nnkCall(
nnkIdent(!"writeln"), nnkIdent(!"writeLine"),
nnkExprEqExpr( nnkExprEqExpr(
nnkIdent(!"file"), nnkIdent(!"file"),
nnkIdent(!"stdout") nnkIdent(!"stdout")

View file

@ -53,7 +53,7 @@ The following example shows a generic binary tree can be modelled:
add(root, newNode("hallo")) # instantiates generic procs ``newNode`` and add(root, newNode("hallo")) # instantiates generic procs ``newNode`` and
add(root, newNode("world")) # ``add`` add(root, newNode("world")) # ``add``
for str in inorder(root): for str in inorder(root):
writeln(stdout, str) writeLine(stdout, str)
Is operator Is operator

View file

@ -132,7 +132,7 @@ to supply any type of first argument for procedures:
echo("abc".len) # is the same as echo(len("abc")) echo("abc".len) # is the same as echo(len("abc"))
echo("abc".toUpper()) echo("abc".toUpper())
echo({'a', 'b', 'c'}.card) echo({'a', 'b', 'c'}.card)
stdout.writeln("Hallo") # the same as writeln(stdout, "Hallo") stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo")
Another way to look at the method call syntax is that it provides the missing Another way to look at the method call syntax is that it provides the missing
postfix notation. postfix notation.

View file

@ -77,10 +77,10 @@ special ``:`` syntax:
quit("cannot open: " & fn) quit("cannot open: " & fn)
withFile(txt, "ttempl3.txt", fmWrite): withFile(txt, "ttempl3.txt", fmWrite):
txt.writeln("line 1") txt.writeLine("line 1")
txt.writeln("line 2") txt.writeLine("line 2")
In the example the two ``writeln`` statements are bound to the ``actions`` In the example the two ``writeLine`` statements are bound to the ``actions``
parameter. parameter.
@ -206,8 +206,8 @@ template parameter, it is an inject'ed symbol:
... ...
withFile(txt, "ttempl3.txt", fmWrite): withFile(txt, "ttempl3.txt", fmWrite):
txt.writeln("line 1") txt.writeLine("line 1")
txt.writeln("line 2") txt.writeLine("line 2")
The ``inject`` and ``gensym`` pragmas are second class annotations; they have The ``inject`` and ``gensym`` pragmas are second class annotations; they have
@ -299,7 +299,7 @@ variable number of arguments:
# add a call to the statement list that writes ": " # add a call to the statement list that writes ": "
add(result, newCall("write", newIdentNode("stdout"), newStrLitNode(": "))) add(result, newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
# add a call to the statement list that writes the expressions value: # add a call to the statement list that writes the expressions value:
add(result, newCall("writeln", newIdentNode("stdout"), n[i])) add(result, newCall("writeLine", newIdentNode("stdout"), n[i]))
var var
a: array [0..10, int] a: array [0..10, int]
@ -314,15 +314,15 @@ The macro call expands to:
.. code-block:: nim .. code-block:: nim
write(stdout, "a[0]") write(stdout, "a[0]")
write(stdout, ": ") write(stdout, ": ")
writeln(stdout, a[0]) writeLine(stdout, a[0])
write(stdout, "a[1]") write(stdout, "a[1]")
write(stdout, ": ") write(stdout, ": ")
writeln(stdout, a[1]) writeLine(stdout, a[1])
write(stdout, "x") write(stdout, "x")
write(stdout, ": ") write(stdout, ": ")
writeln(stdout, x) writeLine(stdout, x)
Arguments that are passed to a ``varargs`` parameter are wrapped in an array Arguments that are passed to a ``varargs`` parameter are wrapped in an array
@ -333,7 +333,7 @@ children.
BindSym BindSym
------- -------
The above ``debug`` macro relies on the fact that ``write``, ``writeln`` and The above ``debug`` macro relies on the fact that ``write``, ``writeLine`` and
``stdout`` are declared in the system module and thus visible in the ``stdout`` are declared in the system module and thus visible in the
instantiating context. There is a way to use bound identifiers instantiating context. There is a way to use bound identifiers
(aka `symbols`:idx:) instead of using unbound identifiers. The ``bindSym`` (aka `symbols`:idx:) instead of using unbound identifiers. The ``bindSym``
@ -348,7 +348,7 @@ builtin can be used for that:
# we can bind symbols in scope via 'bindSym': # we can bind symbols in scope via 'bindSym':
add(result, newCall(bindSym"write", bindSym"stdout", toStrLit(n[i]))) add(result, newCall(bindSym"write", bindSym"stdout", toStrLit(n[i])))
add(result, newCall(bindSym"write", bindSym"stdout", newStrLitNode(": "))) add(result, newCall(bindSym"write", bindSym"stdout", newStrLitNode(": ")))
add(result, newCall(bindSym"writeln", bindSym"stdout", n[i])) add(result, newCall(bindSym"writeLine", bindSym"stdout", n[i]))
var var
a: array [0..10, int] a: array [0..10, int]
@ -363,17 +363,17 @@ The macro call expands to:
.. code-block:: nim .. code-block:: nim
write(stdout, "a[0]") write(stdout, "a[0]")
write(stdout, ": ") write(stdout, ": ")
writeln(stdout, a[0]) writeLine(stdout, a[0])
write(stdout, "a[1]") write(stdout, "a[1]")
write(stdout, ": ") write(stdout, ": ")
writeln(stdout, a[1]) writeLine(stdout, a[1])
write(stdout, "x") write(stdout, "x")
write(stdout, ": ") write(stdout, ": ")
writeln(stdout, x) writeLine(stdout, x)
However, the symbols ``write``, ``writeln`` and ``stdout`` are already bound However, the symbols ``write``, ``writeLine`` and ``stdout`` are already bound
and are not looked up again. As the example shows, ``bindSym`` does work with and are not looked up again. As the example shows, ``bindSym`` does work with
overloaded symbols implicitly. overloaded symbols implicitly.

View file

@ -272,7 +272,7 @@ parameter is of the type ``varargs`` it is treated specially and it can match
.. code-block:: nim .. code-block:: nim
template optWrite{ template optWrite{
write(f, x) write(f, x)
((write|writeln){w})(f, y) ((write|writeLine){w})(f, y)
}(x, y: varargs[expr], f: File, w: expr) = }(x, y: varargs[expr], f: File, w: expr) =
w(f, x, y) w(f, x, y)

View file

@ -207,7 +207,7 @@ for any type:
echo("abc".len) # is the same as echo(len("abc")) echo("abc".len) # is the same as echo(len("abc"))
echo("abc".toUpper()) echo("abc".toUpper())
echo({'a', 'b', 'c'}.card) echo({'a', 'b', 'c'}.card)
stdout.writeln("Hallo") # the same as writeln(stdout, "Hallo") stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo")
(Another way to look at the method call syntax is that it provides the missing (Another way to look at the method call syntax is that it provides the missing
postfix notation.) postfix notation.)
@ -217,9 +217,9 @@ So "pure object oriented" code is easy to write:
.. code-block:: nim .. code-block:: nim
import strutils import strutils
stdout.writeln("Give a list of numbers (separated by spaces): ") stdout.writeLine("Give a list of numbers (separated by spaces): ")
stdout.write(stdin.readLine.split.map(parseInt).max.`$`) stdout.write(stdin.readLine.split.map(parseInt).max.`$`)
stdout.writeln(" is the maximum!") stdout.writeLine(" is the maximum!")
Properties Properties
@ -535,7 +535,7 @@ containers:
add(root, newNode("hello")) # instantiates ``newNode`` and ``add`` add(root, newNode("hello")) # instantiates ``newNode`` and ``add``
add(root, "world") # instantiates the second ``add`` proc add(root, "world") # instantiates the second ``add`` proc
for str in preorder(root): for str in preorder(root):
stdout.writeln(str) stdout.writeLine(str)
The example shows a generic binary tree. Depending on context, the brackets are The example shows a generic binary tree. Depending on context, the brackets are
used either to introduce type parameters or to instantiate a generic proc, used either to introduce type parameters or to instantiate a generic proc,
@ -580,7 +580,7 @@ simple proc for logging:
debug = true debug = true
proc log(msg: string) {.inline.} = proc log(msg: string) {.inline.} =
if debug: stdout.writeln(msg) if debug: stdout.writeLine(msg)
var var
x = 4 x = 4
@ -597,7 +597,7 @@ Turning the ``log`` proc into a template solves this problem:
debug = true debug = true
template log(msg: string) = template log(msg: string) =
if debug: stdout.writeln(msg) if debug: stdout.writeLine(msg)
var var
x = 4 x = 4
@ -627,10 +627,10 @@ via a special ``:`` syntax:
quit("cannot open: " & fn) quit("cannot open: " & fn)
withFile(txt, "ttempl3.txt", fmWrite): withFile(txt, "ttempl3.txt", fmWrite):
txt.writeln("line 1") txt.writeLine("line 1")
txt.writeln("line 2") txt.writeLine("line 2")
In the example the two ``writeln`` statements are bound to the ``body`` In the example the two ``writeLine`` statements are bound to the ``body``
parameter. The ``withFile`` template contains boilerplate code and helps to parameter. The ``withFile`` template contains boilerplate code and helps to
avoid a common bug: to forget to close the file. Note how the avoid a common bug: to forget to close the file. Note how the
``let fn = filename`` statement ensures that ``filename`` is evaluated only ``let fn = filename`` statement ensures that ``filename`` is evaluated only
@ -684,7 +684,7 @@ variable number of arguments:
# add a call to the statement list that writes ": " # add a call to the statement list that writes ": "
result.add(newCall("write", newIdentNode("stdout"), newStrLitNode(": "))) result.add(newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
# add a call to the statement list that writes the expressions value: # add a call to the statement list that writes the expressions value:
result.add(newCall("writeln", newIdentNode("stdout"), n[i])) result.add(newCall("writeLine", newIdentNode("stdout"), n[i]))
var var
a: array[0..10, int] a: array[0..10, int]
@ -699,15 +699,15 @@ The macro call expands to:
.. code-block:: nim .. code-block:: nim
write(stdout, "a[0]") write(stdout, "a[0]")
write(stdout, ": ") write(stdout, ": ")
writeln(stdout, a[0]) writeLine(stdout, a[0])
write(stdout, "a[1]") write(stdout, "a[1]")
write(stdout, ": ") write(stdout, ": ")
writeln(stdout, a[1]) writeLine(stdout, a[1])
write(stdout, "x") write(stdout, "x")
write(stdout, ": ") write(stdout, ": ")
writeln(stdout, x) writeLine(stdout, x)

View file

@ -4,4 +4,4 @@ write(stdout, "Content-type: text/html\n\n")
write(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n") write(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n")
write(stdout, "<html><head><title>Test</title></head><body>\n") write(stdout, "<html><head><title>Test</title></head><body>\n")
write(stdout, "Hello!") write(stdout, "Hello!")
writeln(stdout, "</body></html>") writeLine(stdout, "</body></html>")

View file

@ -7,6 +7,6 @@ writeContentType()
write(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n") write(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n")
write(stdout, "<html><head><title>Test</title></head><body>\n") write(stdout, "<html><head><title>Test</title></head><body>\n")
writeln(stdout, "name: " & myData["name"]) writeLine(stdout, "name: " & myData["name"])
writeln(stdout, "password: " & myData["password"]) writeLine(stdout, "password: " & myData["password"])
writeln(stdout, "</body></html>") writeLine(stdout, "</body></html>")

View file

@ -369,7 +369,7 @@ iterator split*(s: string, sep: Regex): string =
## ##
## .. code-block:: nim ## .. code-block:: nim
## for word in split("00232this02939is39an22example111", re"\d+"): ## for word in split("00232this02939is39an22example111", re"\d+"):
## writeln(stdout, word) ## writeLine(stdout, word)
## ##
## Results in: ## Results in:
## ##

View file

@ -307,7 +307,7 @@ proc defaultMsgHandler*(filename: string, line, col: int, msgkind: MsgKind,
let a = messages[msgkind] % arg let a = messages[msgkind] % arg
let message = "$1($2, $3) $4: $5" % [filename, $line, $col, $mc, a] let message = "$1($2, $3) $4: $5" % [filename, $line, $col, $mc, a]
if mc == mcError: raise newException(EParseError, message) if mc == mcError: raise newException(EParseError, message)
else: writeln(stdout, message) else: writeLine(stdout, message)
proc defaultFindFile*(filename: string): string {.procvar.} = proc defaultFindFile*(filename: string): string {.procvar.} =
if existsFile(filename): result = filename if existsFile(filename): result = filename

View file

@ -25,9 +25,9 @@
## # generate content: ## # generate content:
## write(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n") ## write(stdout, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n")
## write(stdout, "<html><head><title>Test</title></head><body>\n") ## write(stdout, "<html><head><title>Test</title></head><body>\n")
## writeln(stdout, "your name: " & myData["name"]) ## writeLine(stdout, "your name: " & myData["name"])
## writeln(stdout, "your password: " & myData["password"]) ## writeLine(stdout, "your password: " & myData["password"])
## writeln(stdout, "</body></html>") ## writeLine(stdout, "</body></html>")
import strutils, os, strtabs, cookies import strutils, os, strtabs, cookies

View file

@ -132,12 +132,12 @@ method log*(logger: Logger, level: Level, args: varargs[string, `$`]) {.
method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) = method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) =
## Logs to the console using ``logger`` only. ## Logs to the console using ``logger`` only.
if level >= logger.levelThreshold: if level >= logger.levelThreshold:
writeln(stdout, substituteLog(logger.fmtStr, level, args)) writeLine(stdout, substituteLog(logger.fmtStr, level, args))
method log*(logger: FileLogger, level: Level, args: varargs[string, `$`]) = method log*(logger: FileLogger, level: Level, args: varargs[string, `$`]) =
## Logs to a file using ``logger`` only. ## Logs to a file using ``logger`` only.
if level >= logger.levelThreshold: if level >= logger.levelThreshold:
writeln(logger.f, substituteLog(logger.fmtStr, level, args)) writeLine(logger.f, substituteLog(logger.fmtStr, level, args))
proc defaultFilename*(): string = proc defaultFilename*(): string =
## Returns the default filename for a logger. ## Returns the default filename for a logger.
@ -228,7 +228,7 @@ method log*(logger: RollingFileLogger, level: Level, args: varargs[string, `$`])
logger.curLine = 0 logger.curLine = 0
logger.f = open(logger.baseName, logger.baseMode, bufSize = logger.bufSize) logger.f = open(logger.baseName, logger.baseMode, bufSize = logger.bufSize)
writeln(logger.f, substituteLog(logger.fmtStr, level, args)) writeLine(logger.f, substituteLog(logger.fmtStr, level, args))
logger.curLine.inc logger.curLine.inc
# -------- # --------

View file

@ -155,7 +155,7 @@ proc writeProfile() {.noconv.} =
var f: File var f: File
if open(f, filename, fmWrite): if open(f, filename, fmWrite):
sort(profileData, cmpEntries) sort(profileData, cmpEntries)
writeln(f, "total executions of each stack trace:") writeLine(f, "total executions of each stack trace:")
var entries = 0 var entries = 0
for i in 0..high(profileData): for i in 0..high(profileData):
if profileData[i] != nil: inc entries if profileData[i] != nil: inc entries
@ -175,13 +175,13 @@ proc writeProfile() {.noconv.} =
for i in 0..min(100, entries-1): for i in 0..min(100, entries-1):
if profileData[i].total > 1: if profileData[i].total > 1:
inc sum, profileData[i].total inc sum, profileData[i].total
writeln(f, "Entry: ", i+1, "/", entries, " Calls: ", writeLine(f, "Entry: ", i+1, "/", entries, " Calls: ",
profileData[i].total // totalCalls, " [sum: ", sum, "; ", profileData[i].total // totalCalls, " [sum: ", sum, "; ",
sum // totalCalls, "]") sum // totalCalls, "]")
for ii in 0..high(StackTrace): for ii in 0..high(StackTrace):
let procname = profileData[i].st[ii] let procname = profileData[i].st[ii]
if isNil(procname): break if isNil(procname): break
writeln(f, " ", procname, " ", perProc[$procname] // totalCalls) writeLine(f, " ", procname, " ", perProc[$procname] // totalCalls)
close(f) close(f)
echo "... done" echo "... done"
else: else:

View file

@ -1323,7 +1323,7 @@ proc ra(n: SqlNode, s: var string, indent: int) =
# where: x.name == y.name # where: x.name == y.name
#db.select(fromm = [t1, t2], where = t1.name == t2.name): #db.select(fromm = [t1, t2], where = t1.name == t2.name):
#for x, y, z in db.select(fromm = a, b where = a.name == b.name): #for x, y, z in db.select(fromm = a, b where = a.name == b.name):
# writeln x, y, z # writeLine x, y, z
proc renderSQL*(n: SqlNode): string = proc renderSQL*(n: SqlNode): string =
## Converts an SQL abstract syntax tree to its string representation. ## Converts an SQL abstract syntax tree to its string representation.

View file

@ -979,7 +979,7 @@ iterator split*(s: string, sep: Peg): string =
## ##
## .. code-block:: nim ## .. code-block:: nim
## for word in split("00232this02939is39an22example111", peg"\d+"): ## for word in split("00232this02939is39an22example111", peg"\d+"):
## writeln(stdout, word) ## writeLine(stdout, word)
## ##
## Results in: ## Results in:
## ##

View file

@ -117,7 +117,12 @@ proc write*(s: Stream, x: string) =
## terminating zero is written. ## terminating zero is written.
writeData(s, cstring(x), x.len) writeData(s, cstring(x), x.len)
proc writeln*(s: Stream, args: varargs[string, `$`]) = proc writeLn*(s: Stream, args: varargs[string, `$`]) {.deprecated.} =
## **Deprecated since version 0.11.4:** Use **writeLine** instead.
for str in args: write(s, str)
write(s, "\n")
proc writeLine*(s: Stream, args: varargs[string, `$`]) =
## writes one or more strings to the the stream `s` followed ## writes one or more strings to the the stream `s` followed
## by a new line. No length field or terminating zero is written. ## by a new line. No length field or terminating zero is written.
for str in args: write(s, str) for str in args: write(s, str)

View file

@ -206,7 +206,7 @@ iterator split*(s: string, seps: set[char] = Whitespace): string =
## ##
## .. code-block:: nim ## .. code-block:: nim
## for word in split(" this is an example "): ## for word in split(" this is an example "):
## writeln(stdout, word) ## writeLine(stdout, word)
## ##
## ...generates this output: ## ...generates this output:
## ##
@ -220,7 +220,7 @@ iterator split*(s: string, seps: set[char] = Whitespace): string =
## ##
## .. code-block:: nim ## .. code-block:: nim
## for word in split(";;this;is;an;;example;;;", {';'}): ## for word in split(";;this;is;an;;example;;;", {';'}):
## writeln(stdout, word) ## writeLine(stdout, word)
## ##
## ...produces the same output as the first example. The code: ## ...produces the same output as the first example. The code:
## ##
@ -228,7 +228,7 @@ iterator split*(s: string, seps: set[char] = Whitespace): string =
## let date = "2012-11-20T22:08:08.398990" ## let date = "2012-11-20T22:08:08.398990"
## let separators = {' ', '-', ':', 'T'} ## let separators = {' ', '-', ':', 'T'}
## for number in split(date, separators): ## for number in split(date, separators):
## writeln(stdout, number) ## writeLine(stdout, number)
## ##
## ...results in: ## ...results in:
## ##
@ -259,7 +259,7 @@ iterator split*(s: string, sep: char): string =
## ##
## .. code-block:: nim ## .. code-block:: nim
## for word in split(";;this;is;an;;example;;;", ';'): ## for word in split(";;this;is;an;;example;;;", ';'):
## writeln(stdout, word) ## writeLine(stdout, word)
## ##
## Results in: ## Results in:
## ##
@ -309,7 +309,7 @@ iterator splitLines*(s: string): string =
## ##
## .. code-block:: nim ## .. code-block:: nim
## for line in splitLines("\nthis\nis\nan\n\nexample\n"): ## for line in splitLines("\nthis\nis\nan\n\nexample\n"):
## writeln(stdout, line) ## writeLine(stdout, line)
## ##
## Results in: ## Results in:
## ##
@ -571,7 +571,7 @@ iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[
## ##
## .. code-block:: nim ## .. code-block:: nim
## for word in tokenize(" this is an example "): ## for word in tokenize(" this is an example "):
## writeln(stdout, word) ## writeLine(stdout, word)
## ##
## Results in: ## Results in:
## ##

View file

@ -430,8 +430,8 @@ macro styledEcho*(m: varargs[expr]): stmt =
case item.kind case item.kind
of nnkStrLit..nnkTripleStrLit: of nnkStrLit..nnkTripleStrLit:
if i == m.len - 1: if i == m.len - 1:
# optimize if string literal is last, just call writeln # optimize if string literal is last, just call writeLine
result.add(newCall(bindSym"writeln", bindSym"stdout", item)) result.add(newCall(bindSym"writeLine", bindSym"stdout", item))
if reset: result.add(newCall(bindSym"resetAttributes")) if reset: result.add(newCall(bindSym"resetAttributes"))
return return
else: else:
@ -470,7 +470,7 @@ when not defined(testing) and isMainModule:
writeStyled("styled text ", {styleBright, styleBlink, styleUnderscore}) writeStyled("styled text ", {styleBright, styleBlink, styleUnderscore})
setBackGroundColor(bgCyan, true) setBackGroundColor(bgCyan, true)
setForeGroundColor(fgBlue) setForeGroundColor(fgBlue)
writeln(stdout, "ordinary text") writeLine(stdout, "ordinary text")
styledEcho("styled text ", {styleBright, styleBlink, styleUnderscore}) styledEcho("styled text ", {styleBright, styleBlink, styleUnderscore})

View file

@ -898,7 +898,7 @@ proc contains*[T](x: set[T], y: T): bool {.magic: "InSet", noSideEffect.}
## ##
## .. code-block:: Nim ## .. code-block:: Nim
## var s: set[range['a'..'z']] = {'a'..'c'} ## var s: set[range['a'..'z']] = {'a'..'c'}
## writeln(stdout, 'b' in s) ## writeLine(stdout, 'b' in s)
## ##
## If ``in`` had been declared as ``[T](elem: T, s: set[T])`` then ``T`` would ## If ``in`` had been declared as ``[T](elem: T, s: set[T])`` then ``T`` would
## have been bound to ``char``. But ``s`` is not compatible to type ## have been bound to ``char``. But ``s`` is not compatible to type
@ -2269,7 +2269,7 @@ proc echo*(x: varargs[expr, `$`]) {.magic: "Echo", tags: [WriteIOEffect],
## Special built-in that takes a variable number of arguments. Each argument ## Special built-in that takes a variable number of arguments. Each argument
## is converted to a string via ``$``, so it works for user-defined ## is converted to a string via ``$``, so it works for user-defined
## types that have an overloaded ``$`` operator. ## types that have an overloaded ``$`` operator.
## It is roughly equivalent to ``writeln(stdout, x); flushFile(stdout)``, but ## It is roughly equivalent to ``writeLine(stdout, x); flushFile(stdout)``, but
## available for the JavaScript target too. ## available for the JavaScript target too.
## ##
## Unlike other IO operations this is guaranteed to be thread-safe as ## Unlike other IO operations this is guaranteed to be thread-safe as
@ -2526,7 +2526,11 @@ when not defined(JS): #and not defined(NimrodVM):
## Returns ``false`` if the end of the file has been reached, ``true`` ## Returns ``false`` if the end of the file has been reached, ``true``
## otherwise. If ``false`` is returned `line` contains no new data. ## otherwise. If ``false`` is returned `line` contains no new data.
proc writeln*[Ty](f: File, x: varargs[Ty, `$`]) {.inline, proc writeLn*[Ty](f: File, x: varargs[Ty, `$`]) {.inline,
tags: [WriteIOEffect], benign, deprecated.}
## **Deprecated since version 0.11.4:** Use **writeLine** instead.
proc writeLine*[Ty](f: File, x: varargs[Ty, `$`]) {.inline,
tags: [WriteIOEffect], benign.} tags: [WriteIOEffect], benign.}
## writes the values `x` to `f` and then writes "\n". ## writes the values `x` to `f` and then writes "\n".
## May throw an IO exception. ## May throw an IO exception.

View file

@ -117,7 +117,7 @@ proc dbgRepr(p: pointer, typ: PNimType): string =
proc writeVariable(stream: File, slot: VarSlot) = proc writeVariable(stream: File, slot: VarSlot) =
write(stream, slot.name) write(stream, slot.name)
write(stream, " = ") write(stream, " = ")
writeln(stream, dbgRepr(slot.address, slot.typ)) writeLine(stream, dbgRepr(slot.address, slot.typ))
proc listFrame(stream: File, f: PFrame) = proc listFrame(stream: File, f: PFrame) =
write(stream, EndbBeg) write(stream, EndbBeg)
@ -125,7 +125,7 @@ proc listFrame(stream: File, f: PFrame) =
write(stream, f.len) write(stream, f.len)
write(stream, " slots):\n") write(stream, " slots):\n")
for i in 0 .. f.len-1: for i in 0 .. f.len-1:
writeln(stream, getLocal(f, i).name) writeLine(stream, getLocal(f, i).name)
write(stream, EndbEnd) write(stream, EndbEnd)
proc listLocals(stream: File, f: PFrame) = proc listLocals(stream: File, f: PFrame) =
@ -141,7 +141,7 @@ proc listGlobals(stream: File) =
write(stream, EndbBeg) write(stream, EndbBeg)
write(stream, "| Globals:\n") write(stream, "| Globals:\n")
for i in 0 .. getGlobalLen()-1: for i in 0 .. getGlobalLen()-1:
writeln(stream, getGlobal(i).name) writeLine(stream, getGlobal(i).name)
write(stream, EndbEnd) write(stream, EndbEnd)
proc debugOut(msg: cstring) = proc debugOut(msg: cstring) =

View file

@ -208,10 +208,15 @@ proc endOfFile(f: File): bool =
ungetc(c, f) ungetc(c, f)
return c < 0'i32 return c < 0'i32
proc writeln[Ty](f: File, x: varargs[Ty, `$`]) = proc writeLn[Ty](f: File, x: varargs[Ty, `$`]) =
for i in items(x): write(f, i) for i in items(x): write(f, i)
write(f, "\n") write(f, "\n")
proc writeLine[Ty](f: File, x: varargs[Ty, `$`]) =
for i in items(x): write(f, i)
write(f, "\n")
proc rawEcho(x: string) {.inline, compilerproc.} = write(stdout, x) proc rawEcho(x: string) {.inline, compilerproc.} = write(stdout, x)
proc rawEchoNL() {.inline, compilerproc.} = write(stdout, "\n") proc rawEchoNL() {.inline, compilerproc.} = write(stdout, "\n")

View file

@ -11,8 +11,8 @@ type
proc len(x: TMyType): int {.inline.} = return x.len proc len(x: TMyType): int {.inline.} = return x.len
proc x(s: TMyType, len: int) = proc x(s: TMyType, len: int) =
writeln(stdout, len(s)) writeLine(stdout, len(s))
var var
m: TMyType m: TMyType

View file

@ -10,6 +10,6 @@ import mambsym1, times
var var
v = mDec #ERROR_MSG ambiguous identifier v = mDec #ERROR_MSG ambiguous identifier
writeln(stdout, ord(v)) writeLine(stdout, ord(v))

View file

@ -22,10 +22,10 @@ proc test() =
b = a # perform a deep copy here! b = a # perform a deep copy here!
b.seq = @["xyz", "huch", "was", "soll"] b.seq = @["xyz", "huch", "was", "soll"]
writeln(stdout, len(a.seq)) writeLine(stdout, len(a.seq))
writeln(stdout, a.seq[3]) writeLine(stdout, a.seq[3])
writeln(stdout, len(b.seq)) writeLine(stdout, len(b.seq))
writeln(stdout, b.seq[3]) writeLine(stdout, b.seq[3])
writeln(stdout, b.y) writeLine(stdout, b.y)
test() test()

View file

@ -16,8 +16,8 @@ proc main() =
p = find(example, "=") p = find(example, "=")
a = substr(example, 0, p-1) a = substr(example, 0, p-1)
b = substr(example, p+1) b = substr(example, p+1)
writeln(stdout, a & '=' & b) writeLine(stdout, a & '=' & b)
#writeln(stdout, b) #writeLine(stdout, b)
main() main()
#OUT TEMP=C:\Programs\xyz\bin #OUT TEMP=C:\Programs\xyz\bin

View file

@ -13,7 +13,7 @@ type
proc forw: int {. .} proc forw: int {. .}
proc lier(): int {.raises: [IO2Error].} = proc lier(): int {.raises: [IO2Error].} =
writeln stdout, "arg" writeLine stdout, "arg"
proc forw: int = proc forw: int =
raise newException(IOError, "arg") raise newException(IOError, "arg")

View file

@ -13,7 +13,7 @@ type
proc forw: int {.raises: [].} proc forw: int {.raises: [].}
proc lier(): int {.raises: [IOError].} = proc lier(): int {.raises: [IOError].} =
writeln stdout, "arg" writeLine stdout, "arg"
proc forw: int = proc forw: int =
raise newException(IOError, "arg") raise newException(IOError, "arg")

View file

@ -12,7 +12,7 @@ type
EIO2 = ref object of EIO EIO2 = ref object of EIO
proc raiser(): int {.tags: [TObj, FWriteIO].} = proc raiser(): int {.tags: [TObj, FWriteIO].} =
writeln stdout, "arg" writeLine stdout, "arg"
var o: TObjB var o: TObjB
o.fn = raiser o.fn = raiser

View file

@ -15,7 +15,7 @@ proc q() {.tags: [FIO].} =
nil nil
proc raiser(): int = proc raiser(): int =
writeln stdout, "arg" writeLine stdout, "arg"
if true: if true:
q() q()

View file

@ -63,12 +63,12 @@ proc caseTree(lvl: int = 0): PCaseNode =
if lvl == 3: result = newCaseNode("data item") if lvl == 3: result = newCaseNode("data item")
else: result = newCaseNode(caseTree(lvl+1), caseTree(lvl+1)) else: result = newCaseNode(caseTree(lvl+1), caseTree(lvl+1))
proc finalizeBNode(n: TBNode) = writeln(stdout, n.data) proc finalizeBNode(n: TBNode) = writeLine(stdout, n.data)
proc finalizeNode(n: PNode) = proc finalizeNode(n: PNode) =
assert(n != nil) assert(n != nil)
write(stdout, "finalizing: ") write(stdout, "finalizing: ")
if isNil(n.data): writeln(stdout, "nil!") if isNil(n.data): writeLine(stdout, "nil!")
else: writeln(stdout, n.data) else: writeLine(stdout, n.data)
var var
id: int = 1 id: int = 1
@ -82,7 +82,7 @@ proc buildTree(depth = 1): PNode =
inc(id) inc(id)
proc returnTree(): PNode = proc returnTree(): PNode =
writeln(stdout, "creating id: " & $id) writeLine(stdout, "creating id: " & $id)
new(result, finalizeNode) new(result, finalizeNode)
result.data = $id result.data = $id
new(result.le, finalizeNode) new(result.le, finalizeNode)
@ -92,26 +92,26 @@ proc returnTree(): PNode =
inc(id) inc(id)
# now create a cycle: # now create a cycle:
writeln(stdout, "creating id (cyclic): " & $id) writeLine(stdout, "creating id (cyclic): " & $id)
var cycle: PNode var cycle: PNode
new(cycle, finalizeNode) new(cycle, finalizeNode)
cycle.data = $id cycle.data = $id
cycle.le = cycle cycle.le = cycle
cycle.ri = cycle cycle.ri = cycle
inc(id) inc(id)
#writeln(stdout, "refcount: " & $refcount(cycle)) #writeLine(stdout, "refcount: " & $refcount(cycle))
#writeln(stdout, "refcount le: " & $refcount(cycle.le)) #writeLine(stdout, "refcount le: " & $refcount(cycle.le))
#writeln(stdout, "refcount ri: " & $refcount(cycle.ri)) #writeLine(stdout, "refcount ri: " & $refcount(cycle.ri))
proc printTree(t: PNode) = proc printTree(t: PNode) =
if t == nil: return if t == nil: return
writeln(stdout, "printing") writeLine(stdout, "printing")
writeln(stdout, t.data) writeLine(stdout, t.data)
printTree(t.le) printTree(t.le)
printTree(t.ri) printTree(t.ri)
proc unsureNew(result: var PNode) = proc unsureNew(result: var PNode) =
writeln(stdout, "creating unsure id: " & $id) writeLine(stdout, "creating unsure id: " & $id)
new(result, finalizeNode) new(result, finalizeNode)
result.data = $id result.data = $id
new(result.le, finalizeNode) new(result.le, finalizeNode)
@ -176,7 +176,7 @@ proc main() =
var s: seq[string] = @[] var s: seq[string] = @[]
for i in 1..100: for i in 1..100:
add s, "hohoho" # test reallocation add s, "hohoho" # test reallocation
writeln(stdout, s[89]) writeLine(stdout, s[89])
write(stdout, "done!\n") write(stdout, "done!\n")
var var
@ -184,7 +184,7 @@ var
s: string s: string
s = "" s = ""
s = "" s = ""
writeln(stdout, repr(caseTree())) writeLine(stdout, repr(caseTree()))
father.t.data = @["ha", "lets", "stress", "it"] father.t.data = @["ha", "lets", "stress", "it"]
father.t.data = @["ha", "lets", "stress", "it"] father.t.data = @["ha", "lets", "stress", "it"]
var t = buildTree() var t = buildTree()
@ -199,5 +199,5 @@ GC_fullCollect()
# the M&S GC fails with this call and it's unclear why. Definitely something # the M&S GC fails with this call and it's unclear why. Definitely something
# we need to fix! # we need to fix!
GC_fullCollect() GC_fullCollect()
writeln(stdout, GC_getStatistics()) writeLine(stdout, GC_getStatistics())
write(stdout, "finished\n") write(stdout, "finished\n")

View file

@ -15,7 +15,7 @@ if find(root, "world"):
for str in items(root): for str in items(root):
stdout.write(str) stdout.write(str)
else: else:
stdout.writeln("BUG") stdout.writeLine("BUG")
var var
r2: PBinaryTree[int] r2: PBinaryTree[int]

View file

@ -92,7 +92,7 @@ when isMainModule:
for str in items(root): for str in items(root):
stdout.write(str) stdout.write(str)
else: else:
stdout.writeln("BUG") stdout.writeLine("BUG")
var var
r2: PBinaryTree[int] r2: PBinaryTree[int]

View file

@ -37,25 +37,25 @@ proc clean[T: SomeOrdinal|SomeNumber](o: var T) {.inline.} = discard
proc clean[T: string|seq](o: var T) {.inline.} = proc clean[T: string|seq](o: var T) {.inline.} =
o = nil o = nil
proc clean[T,D] (o: ref TItem[T,D]) {.inline.} = proc clean[T,D] (o: ref TItem[T,D]) {.inline.} =
when (D is string) : when (D is string) :
o.value = nil o.value = nil
else : else :
o.val_set = false o.val_set = false
proc isClean[T,D] (it: ref TItem[T,D]): bool {.inline.} = proc isClean[T,D] (it: ref TItem[T,D]): bool {.inline.} =
when (D is string) : when (D is string) :
return it.value == nil return it.value == nil
else : else :
return not it.val_set return not it.val_set
proc isClean[T,D](n: PNode[T,D], x: int): bool {.inline.} = proc isClean[T,D](n: PNode[T,D], x: int): bool {.inline.} =
when (D is string): when (D is string):
return n.slots[x].value == nil return n.slots[x].value == nil
else: else:
return not n.slots[x].val_set return not n.slots[x].val_set
proc setItem[T,D](Akey: T, Avalue: D, ANode: PNode[T,D]): ref TItem[T,D] {.inline.} = proc setItem[T,D](Akey: T, Avalue: D, ANode: PNode[T,D]): ref TItem[T,D] {.inline.} =
new(result) new(result)
result.key = Akey result.key = Akey
result.value = Avalue result.value = Avalue
@ -72,8 +72,8 @@ template binSearchImpl *(docmp: expr) {.immediate.} =
var H = haystack.len -1 var H = haystack.len -1
while result <= H : while result <= H :
var I {.inject.} = (result + H) shr 1 var I {.inject.} = (result + H) shr 1
var SW = docmp var SW = docmp
if SW < 0: result = I + 1 if SW < 0: result = I + 1
else: else:
H = I - 1 H = I - 1
if SW == 0 : bFound = true if SW == 0 : bFound = true
@ -85,14 +85,14 @@ proc bSearch[T,D] (haystack: PNode[T,D], needle:T): int {.inline.} =
proc DeleteItem[T,D] (n: PNode[T,D], x: int): PNode[T,D] {.inline.} = proc DeleteItem[T,D] (n: PNode[T,D], x: int): PNode[T,D] {.inline.} =
var w = n.slots[x] var w = n.slots[x]
if w.node != nil : if w.node != nil :
clean(w) clean(w)
return n return n
dec(n.count) dec(n.count)
if n.count > 0 : if n.count > 0 :
for i in countup(x, n.count -1) : n.slots[i] = n.slots[i + 1] for i in countup(x, n.count -1) : n.slots[i] = n.slots[i + 1]
n.slots[n.count] = nil n.slots[n.count] = nil
case n.count case n.count
of cLen1 : setLen(n.slots, cLen1) of cLen1 : setLen(n.slots, cLen1)
of cLen2 : setLen(n.slots, cLen2) of cLen2 : setLen(n.slots, cLen2)
of cLen3 : setLen(n.slots, cLen3) of cLen3 : setLen(n.slots, cLen3)
@ -106,7 +106,7 @@ proc DeleteItem[T,D] (n: PNode[T,D], x: int): PNode[T,D] {.inline.} =
n.slots = nil n.slots = nil
n.left = nil n.left = nil
proc internalDelete[T,D] (ANode: PNode[T,D], key: T, Avalue: var D): PNode[T,D] = proc internalDelete[T,D] (ANode: PNode[T,D], key: T, Avalue: var D): PNode[T,D] =
var Path: array[0..20, RPath[T,D]] var Path: array[0..20, RPath[T,D]]
var n = ANode var n = ANode
result = n result = n
@ -126,20 +126,20 @@ proc internalDelete[T,D] (ANode: PNode[T,D], key: T, Avalue: var D): PNode[T,D]
n = n.slots[x].node n = n.slots[x].node
else : else :
n = nil n = nil
else : else :
dec(x) dec(x)
if isClean(n, x) : return if isClean(n, x) : return
Avalue = n.slots[x].value Avalue = n.slots[x].value
var n2 = DeleteItem(n, x) var n2 = DeleteItem(n, x)
dec(h) dec(h)
while (n2 != n) and (h >=0) : while (n2 != n) and (h >=0) :
n = n2 n = n2
var w = addr Path[h] var w = addr Path[h]
x = w.Xi -1 x = w.Xi -1
if x >= 0 : if x >= 0 :
if (n == nil) and isClean(w.Nd, x) : if (n == nil) and isClean(w.Nd, x) :
n = w.Nd n = w.Nd
n.slots[x].node = nil n.slots[x].node = nil
n2 = DeleteItem(n, x) n2 = DeleteItem(n, x)
else : else :
w.Nd.slots[x].node = n w.Nd.slots[x].node = n
@ -161,7 +161,7 @@ proc internalFind[T,D] (n: PNode[T,D], key: T): ref TItem[T,D] {.inline.} =
wn = wn.left wn = wn.left
else : else :
x = (-x) -1 x = (-x) -1
if x < wn.count : if x < wn.count :
wn = wn.slots[x].node wn = wn.slots[x].node
else : else :
return nil return nil
@ -171,7 +171,7 @@ proc internalFind[T,D] (n: PNode[T,D], key: T): ref TItem[T,D] {.inline.} =
return nil return nil
proc traceTree[T,D](root: PNode[T,D]) = proc traceTree[T,D](root: PNode[T,D]) =
proc traceX(x: int) = proc traceX(x: int) =
write stdout, "(" write stdout, "("
write stdout, x write stdout, x
write stdout, ") " write stdout, ") "
@ -184,7 +184,7 @@ proc traceTree[T,D](root: PNode[T,D]) =
proc traceln(space: string) = proc traceln(space: string) =
writeln stdout, "" writeLine stdout, ""
write stdout, space write stdout, space
proc doTrace(n: PNode[T,D], level: int) = proc doTrace(n: PNode[T,D], level: int) =
@ -192,7 +192,7 @@ proc traceTree[T,D](root: PNode[T,D]) =
traceln(space) traceln(space)
write stdout, "node: " write stdout, "node: "
if n == nil: if n == nil:
writeln stdout, "is empty" writeLine stdout, "is empty"
return return
write stdout, n.count write stdout, n.count
write stdout, " elements: " write stdout, " elements: "
@ -204,7 +204,7 @@ proc traceTree[T,D](root: PNode[T,D]) =
if el != nil and not isClean(el): if el != nil and not isClean(el):
traceln(space) traceln(space)
traceX(i) traceX(i)
if i >= n.count: if i >= n.count:
write stdout, "error " write stdout, "error "
else: else:
traceEl(el) traceEl(el)
@ -219,14 +219,14 @@ proc traceTree[T,D](root: PNode[T,D]) =
else : write stdout, el.key else : write stdout, el.key
if el.node != nil: doTrace(el.node, level +1) if el.node != nil: doTrace(el.node, level +1)
else : write stdout, " empty " else : write stdout, " empty "
writeln stdout,"" writeLine stdout,""
doTrace(root, 0) doTrace(root, 0)
proc InsertItem[T,D](APath: RPath[T,D], ANode:PNode[T,D], Akey: T, Avalue: D) = proc InsertItem[T,D](APath: RPath[T,D], ANode:PNode[T,D], Akey: T, Avalue: D) =
var x = - APath.Xi var x = - APath.Xi
inc(APath.Nd.count) inc(APath.Nd.count)
case APath.Nd.count case APath.Nd.count
of cLen1: setLen(APath.Nd.slots, cLen2) of cLen1: setLen(APath.Nd.slots, cLen2)
of cLen2: setLen(APath.Nd.slots, cLen3) of cLen2: setLen(APath.Nd.slots, cLen3)
of cLen3: setLen(APath.Nd.slots, cLenCenter) of cLen3: setLen(APath.Nd.slots, cLenCenter)
@ -286,7 +286,7 @@ proc internalPut[T,D](ANode: ref TNode[T,D], Akey: T, Avalue: D, Oldvalue: var D
if x <= 0 : if x <= 0 :
Path[h].Nd = n Path[h].Nd = n
Path[h].Xi = x Path[h].Xi = x
inc(h) inc(h)
if x == 0 : if x == 0 :
n = n.left n = n.left
else : else :
@ -337,40 +337,40 @@ proc CleanTree[T,D](n: PNode[T,D]): PNode[T,D] =
proc VisitAllNodes[T,D](n: PNode[T,D], visit: proc(n: PNode[T,D]): PNode[T,D] {.closure.} ): PNode[T,D] = proc VisitAllNodes[T,D](n: PNode[T,D], visit: proc(n: PNode[T,D]): PNode[T,D] {.closure.} ): PNode[T,D] =
if n != nil : if n != nil :
if n.left != nil : if n.left != nil :
n.left = VisitAllNodes(n.left, visit) n.left = VisitAllNodes(n.left, visit)
for i in 0 .. n.count - 1 : for i in 0 .. n.count - 1 :
var w = n.slots[i] var w = n.slots[i]
if w.node != nil : if w.node != nil :
w.node = VisitAllNodes(w.node, visit) w.node = VisitAllNodes(w.node, visit)
return visit(n) return visit(n)
return nil return nil
proc VisitAllNodes[T,D](n: PNode[T,D], visit: proc(n: PNode[T,D]) {.closure.} ) = proc VisitAllNodes[T,D](n: PNode[T,D], visit: proc(n: PNode[T,D]) {.closure.} ) =
if n != nil: if n != nil:
if n.left != nil : if n.left != nil :
VisitAllNodes(n.left, visit) VisitAllNodes(n.left, visit)
for i in 0 .. n.count - 1 : for i in 0 .. n.count - 1 :
var w = n.slots[i] var w = n.slots[i]
if w.node != nil : if w.node != nil :
VisitAllNodes(w.node, visit) VisitAllNodes(w.node, visit)
visit(n) visit(n)
proc VisitAll[T,D](n: PNode[T,D], visit: proc(Akey: T, Avalue: D) {.closure.} ) = proc VisitAll[T,D](n: PNode[T,D], visit: proc(Akey: T, Avalue: D) {.closure.} ) =
if n != nil: if n != nil:
if n.left != nil : if n.left != nil :
VisitAll(n.left, visit) VisitAll(n.left, visit)
for i in 0 .. n.count - 1 : for i in 0 .. n.count - 1 :
var w = n.slots[i] var w = n.slots[i]
if not w.isClean : if not w.isClean :
visit(w.key, w.value) visit(w.key, w.value)
if w.node != nil : if w.node != nil :
VisitAll(w.node, visit) VisitAll(w.node, visit)
proc VisitAll[T,D](n: PNode[T,D], visit: proc(Akey: T, Avalue: var D):bool {.closure.} ): PNode[T,D] = proc VisitAll[T,D](n: PNode[T,D], visit: proc(Akey: T, Avalue: var D):bool {.closure.} ): PNode[T,D] =
if n != nil: if n != nil:
var n1 = n.left var n1 = n.left
if n1 != nil : if n1 != nil :
var n2 = VisitAll(n1, visit) var n2 = VisitAll(n1, visit)
if n1 != n2 : if n1 != n2 :
n.left = n2 n.left = n2
var i = 0 var i = 0
@ -395,7 +395,7 @@ iterator keys* [T,D] (n: PNode[T,D]): T =
var level = 0 var level = 0
var nd = n var nd = n
var i = -1 var i = -1
while true : while true :
if i < nd.count : if i < nd.count :
Path[level].Nd = nd Path[level].Nd = nd
Path[level].Xi = i Path[level].Xi = i
@ -471,4 +471,4 @@ when isMainModule:
test() test()

View file

@ -50,8 +50,8 @@ proc main*(infile: string, a, b: int, someverylongnamewithtype = 0,
# this should be an error! # this should be an error!
if initBaseLexer(L, infile, 30): nil if initBaseLexer(L, infile, 30): nil
else: else:
writeln(stdout, "could not open: " & infile) writeLine(stdout, "could not open: " & infile)
writeln(stdout, "Success!") writeLine(stdout, "Success!")
call(3, # we use 3 call(3, # we use 3
12, # we use 12 12, # we use 12
43) # we use 43 43) # we use 43

View file

@ -18,7 +18,7 @@ macro debug(n: varargs[expr]): stmt =
# add a call to the statement list that writes ": " # add a call to the statement list that writes ": "
add(result, newCall("write", newIdentNode("stdout"), newStrLitNode(": "))) add(result, newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
# add a call to the statement list that writes the expressions value: # add a call to the statement list that writes the expressions value:
add(result, newCall("writeln", newIdentNode("stdout"), n[i])) add(result, newCall("writeLine", newIdentNode("stdout"), n[i]))
var var
a: array [0..10, int] a: array [0..10, int]

View file

@ -7,8 +7,8 @@ var
i: int i: int
params = paramCount() params = paramCount()
i = 0 i = 0
writeln(stdout, "This exe: " & getAppFilename()) writeLine(stdout, "This exe: " & getAppFilename())
writeln(stdout, "Number of parameters: " & $params) writeLine(stdout, "Number of parameters: " & $params)
while i <= params: while i <= params:
writeln(stdout, paramStr(i)) writeLine(stdout, paramStr(i))
i = i + 1 i = i + 1

View file

@ -1,3 +1,3 @@
# test the new endian magic # test the new endian magic
writeln(stdout, repr(system.cpuEndian)) writeLine(stdout, repr(system.cpuEndian))

View file

@ -22,7 +22,7 @@ macro macrotest(n: expr): stmt {.immediate.} =
result = newNimNode(nnkStmtList, n) result = newNimNode(nnkStmtList, n)
for i in 2..n.len-1: for i in 2..n.len-1:
result.add(newCall("write", n[1], n[i])) result.add(newCall("write", n[1], n[i]))
result.add(newCall("writeln", n[1], newStrLitNode(""))) result.add(newCall("writeLine", n[1], newStrLitNode("")))
macro debug(n: expr): stmt {.immediate.} = macro debug(n: expr): stmt {.immediate.} =
let n = callsite() let n = callsite()
@ -30,7 +30,7 @@ macro debug(n: expr): stmt {.immediate.} =
for i in 1..n.len-1: for i in 1..n.len-1:
result.add(newCall("write", newIdentNode("stdout"), toStrLit(n[i]))) result.add(newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
result.add(newCall("write", newIdentNode("stdout"), newStrLitNode(": "))) result.add(newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
result.add(newCall("writeln", newIdentNode("stdout"), n[i])) result.add(newCall("writeLine", newIdentNode("stdout"), n[i]))
macrotest(stdout, "finally", 4, 5, "variable", "argument lists") macrotest(stdout, "finally", 4, 5, "variable", "argument lists")
macrotest(stdout) macrotest(stdout)
@ -38,7 +38,7 @@ macrotest(stdout)
#GC_disable() #GC_disable()
echo("This was compiled by Nim version " & system.NimVersion) echo("This was compiled by Nim version " & system.NimVersion)
writeln(stdout, "Hello", " World", "!") writeLine(stdout, "Hello", " World", "!")
echo(["a", "b", "c", "d"].len) echo(["a", "b", "c", "d"].len)
for x in items(["What's", "your", "name", "?", ]): for x in items(["What's", "your", "name", "?", ]):

View file

@ -8,8 +8,8 @@ proc main() =
a, b: TTime a, b: TTime
a = getLastModificationTime(paramStr(1)) a = getLastModificationTime(paramStr(1))
b = getLastModificationTime(paramStr(2)) b = getLastModificationTime(paramStr(2))
writeln(stdout, $a) writeLine(stdout, $a)
writeln(stdout, $b) writeLine(stdout, $b)
if a < b: if a < b:
write(stdout, "$2 is newer than $1\n" % [paramStr(1), paramStr(2)]) write(stdout, "$2 is newer than $1\n" % [paramStr(1), paramStr(2)])
else: else:

View file

@ -24,10 +24,10 @@ var size = parseInt (paramStr (1))
var bit = 128 var bit = 128
var byteAcc = 0 var byteAcc = 0
stdout.writeln ("P4") stdout.writeLine ("P4")
stdout.write ($size) stdout.write ($size)
stdout.write (" ") stdout.write (" ")
stdout.writeln ($size) stdout.writeLine ($size)
var fsize = float (size) var fsize = float (size)
for y in 0 .. size-1: for y in 0 .. size-1:

View file

@ -9,4 +9,4 @@ var
x = 1 x = 1
y = high(int) y = high(int)
writeln(stdout, $ ( x +% y ) ) writeLine(stdout, $ ( x +% y ) )

View file

@ -2,141 +2,141 @@ discard """
file: "tvarnums.nim" file: "tvarnums.nim"
output: "Success!" output: "Success!"
""" """
# Test variable length binary integers # Test variable length binary integers
import import
strutils strutils
type type
TBuffer = array [0..10, int8] TBuffer = array [0..10, int8]
proc toVarNum(x: int32, b: var TBuffer) = proc toVarNum(x: int32, b: var TBuffer) =
# encoding: first bit indicates end of number (0 if at end) # encoding: first bit indicates end of number (0 if at end)
# second bit of the first byte denotes the sign (1 --> negative) # second bit of the first byte denotes the sign (1 --> negative)
var a = x var a = x
if x != low(x): if x != low(x):
# low(int) is a special case, # low(int) is a special case,
# because abs() does not work here! # because abs() does not work here!
# we leave x as it is and use the check >% instead of > # we leave x as it is and use the check >% instead of >
# for low(int) this is needed and positive numbers are not affected # for low(int) this is needed and positive numbers are not affected
# anyway # anyway
a = abs(x) a = abs(x)
# first 6 bits: # first 6 bits:
b[0] = toU8(ord(a >% 63'i32) shl 7 or (ord(x < 0'i32) shl 6) or (int(a) and 63)) b[0] = toU8(ord(a >% 63'i32) shl 7 or (ord(x < 0'i32) shl 6) or (int(a) and 63))
a = a shr 6'i32 # skip first 6 bits a = a shr 6'i32 # skip first 6 bits
var i = 1 var i = 1
while a != 0'i32: while a != 0'i32:
b[i] = toU8(ord(a >% 127'i32) shl 7 or (int(a) and 127)) b[i] = toU8(ord(a >% 127'i32) shl 7 or (int(a) and 127))
inc(i) inc(i)
a = a shr 7'i32 a = a shr 7'i32
proc toVarNum64(x: int64, b: var TBuffer) = proc toVarNum64(x: int64, b: var TBuffer) =
# encoding: first bit indicates end of number (0 if at end) # encoding: first bit indicates end of number (0 if at end)
# second bit of the first byte denotes the sign (1 --> negative) # second bit of the first byte denotes the sign (1 --> negative)
var a = x var a = x
if x != low(x): if x != low(x):
# low(int) is a special case, # low(int) is a special case,
# because abs() does not work here! # because abs() does not work here!
# we leave x as it is and use the check >% instead of > # we leave x as it is and use the check >% instead of >
# for low(int) this is needed and positive numbers are not affected # for low(int) this is needed and positive numbers are not affected
# anyway # anyway
a = abs(x) a = abs(x)
# first 6 bits: # first 6 bits:
b[0] = toU8(ord(a >% 63'i64) shl 7 or (ord(x < 0'i64) shl 6) or int(a and 63)) b[0] = toU8(ord(a >% 63'i64) shl 7 or (ord(x < 0'i64) shl 6) or int(a and 63))
a = a shr 6 # skip first 6 bits a = a shr 6 # skip first 6 bits
var i = 1 var i = 1
while a != 0'i64: while a != 0'i64:
b[i] = toU8(ord(a >% 127'i64) shl 7 or int(a and 127)) b[i] = toU8(ord(a >% 127'i64) shl 7 or int(a and 127))
inc(i) inc(i)
a = a shr 7 a = a shr 7
proc toNum64(b: TBuffer): int64 = proc toNum64(b: TBuffer): int64 =
# treat first byte different: # treat first byte different:
result = ze64(b[0]) and 63 result = ze64(b[0]) and 63
var var
i = 0 i = 0
Shift = 6'i64 Shift = 6'i64
while (ze(b[i]) and 128) != 0: while (ze(b[i]) and 128) != 0:
inc(i) inc(i)
result = result or ((ze64(b[i]) and 127) shl Shift) result = result or ((ze64(b[i]) and 127) shl Shift)
inc(Shift, 7) inc(Shift, 7)
if (ze(b[0]) and 64) != 0: # sign bit set? if (ze(b[0]) and 64) != 0: # sign bit set?
result = not result +% 1 result = not result +% 1
# this is the same as ``- result`` # this is the same as ``- result``
# but gives no overflow error for low(int) # but gives no overflow error for low(int)
proc toNum(b: TBuffer): int32 = proc toNum(b: TBuffer): int32 =
# treat first byte different: # treat first byte different:
result = ze(b[0]) and 63 result = ze(b[0]) and 63
var var
i = 0 i = 0
Shift = 6'i32 Shift = 6'i32
while (ze(b[i]) and 128) != 0: while (ze(b[i]) and 128) != 0:
inc(i) inc(i)
result = result or ((int32(ze(b[i])) and 127'i32) shl Shift) result = result or ((int32(ze(b[i])) and 127'i32) shl Shift)
Shift = Shift + 7'i32 Shift = Shift + 7'i32
if (ze(b[0]) and (1 shl 6)) != 0: # sign bit set? if (ze(b[0]) and (1 shl 6)) != 0: # sign bit set?
result = (not result) +% 1'i32 result = (not result) +% 1'i32
# this is the same as ``- result`` # this is the same as ``- result``
# but gives no overflow error for low(int) # but gives no overflow error for low(int)
proc toBinary(x: int64): string = proc toBinary(x: int64): string =
result = newString(64) result = newString(64)
for i in 0..63: for i in 0..63:
result[63-i] = chr((int(x shr i) and 1) + ord('0')) result[63-i] = chr((int(x shr i) and 1) + ord('0'))
proc t64(i: int64) = proc t64(i: int64) =
var var
b: TBuffer b: TBuffer
toVarNum64(i, b) toVarNum64(i, b)
var x = toNum64(b) var x = toNum64(b)
if x != i: if x != i:
writeln(stdout, $i) writeLine(stdout, $i)
writeln(stdout, toBinary(i)) writeLine(stdout, toBinary(i))
writeln(stdout, toBinary(x)) writeLine(stdout, toBinary(x))
proc t32(i: int32) = proc t32(i: int32) =
var var
b: TBuffer b: TBuffer
toVarNum(i, b) toVarNum(i, b)
var x = toNum(b) var x = toNum(b)
if x != i: if x != i:
writeln(stdout, toBinary(i)) writeLine(stdout, toBinary(i))
writeln(stdout, toBinary(x)) writeLine(stdout, toBinary(x))
proc tm(i: int32) = proc tm(i: int32) =
var var
b: TBuffer b: TBuffer
toVarNum64(i, b) toVarNum64(i, b)
var x = toNum(b) var x = toNum(b)
if x != i: if x != i:
writeln(stdout, toBinary(i)) writeLine(stdout, toBinary(i))
writeln(stdout, toBinary(x)) writeLine(stdout, toBinary(x))
t32(0) t32(0)
t32(1) t32(1)
t32(-1) t32(-1)
t32(-100_000) t32(-100_000)
t32(100_000) t32(100_000)
t32(low(int32)) t32(low(int32))
t32(high(int32)) t32(high(int32))
t64(low(int64)) t64(low(int64))
t64(high(int64)) t64(high(int64))
t64(0) t64(0)
t64(-1) t64(-1)
t64(1) t64(1)
t64(1000_000) t64(1000_000)
t64(-1000_000) t64(-1000_000)
tm(0) tm(0)
tm(1) tm(1)
tm(-1) tm(-1)
tm(-100_000) tm(-100_000)
tm(100_000) tm(100_000)
tm(low(int32)) tm(low(int32))
tm(high(int32)) tm(high(int32))
writeln(stdout, "Success!") #OUT Success! writeLine(stdout, "Success!") #OUT Success!

View file

@ -9,7 +9,7 @@ type
proc getPoint( p: var TPoint2d) = proc getPoint( p: var TPoint2d) =
{.breakpoint.} {.breakpoint.}
writeln(stdout, p.x) writeLine(stdout, p.x)
var var
p: TPoint3d p: TPoint3d

View file

@ -8,17 +8,17 @@ import macros
type type
TFigure = object of RootObj # abstract base class: TFigure = object of RootObj # abstract base class:
draw: proc (my: var TFigure) {.nimcall.} # concrete classes implement this draw: proc (my: var TFigure) {.nimcall.} # concrete classes implement this
proc init(f: var TFigure) = proc init(f: var TFigure) =
f.draw = nil f.draw = nil
type type
TCircle = object of TFigure TCircle = object of TFigure
radius: int radius: int
proc drawCircle(my: var TCircle) = stdout.writeln("o " & $my.radius)
proc init(my: var TCircle) = proc drawCircle(my: var TCircle) = stdout.writeLine("o " & $my.radius)
proc init(my: var TCircle) =
init(TFigure(my)) # call base constructor init(TFigure(my)) # call base constructor
my.radius = 5 my.radius = 5
my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawCircle) my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawCircle)
@ -29,13 +29,13 @@ type
proc drawRectangle(my: var TRectangle) = stdout.write("[]") proc drawRectangle(my: var TRectangle) = stdout.write("[]")
proc init(my: var TRectangle) = proc init(my: var TRectangle) =
init(TFigure(my)) # call base constructor init(TFigure(my)) # call base constructor
my.width = 5 my.width = 5
my.height = 10 my.height = 10
my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawRectangle) my.draw = cast[proc (my: var TFigure) {.nimcall.}](drawRectangle)
macro `!` (n: expr): stmt {.immediate.} = macro `!` (n: expr): stmt {.immediate.} =
let n = callsite() let n = callsite()
result = newNimNode(nnkCall, n) result = newNimNode(nnkCall, n)
var dot = newNimNode(nnkDotExpr, n) var dot = newNimNode(nnkDotExpr, n)
@ -60,16 +60,16 @@ type
FHost: int # cannot be accessed from the outside of the module FHost: int # cannot be accessed from the outside of the module
# the `F` prefix is a convention to avoid clashes since # the `F` prefix is a convention to avoid clashes since
# the accessors are named `host` # the accessors are named `host`
proc `host=`*(s: var TSocket, value: int) {.inline.} = proc `host=`*(s: var TSocket, value: int) {.inline.} =
## setter of hostAddr ## setter of hostAddr
s.FHost = value s.FHost = value
proc host*(s: TSocket): int {.inline.} = proc host*(s: TSocket): int {.inline.} =
## getter of hostAddr ## getter of hostAddr
return s.FHost return s.FHost
var var
s: TSocket s: TSocket
s.host = 34 # same as `host=`(s, 34) s.host = 34 # same as `host=`(s, 34)
stdout.write(s.host) stdout.write(s.host)
@ -81,6 +81,6 @@ var
init(r) init(r)
init(c) init(c)
r!draw r!draw
c!draw() c!draw()
#OUT 34[]o 5 #OUT 34[]o 5

View file

@ -2,20 +2,20 @@ discard """
file: "toverflw.nim" file: "toverflw.nim"
output: "the computation overflowed" output: "the computation overflowed"
""" """
# Tests nim's ability to detect overflows # Tests nim's ability to detect overflows
{.push overflowChecks: on.} {.push overflowChecks: on.}
var var
a, b: int a, b: int
a = high(int) a = high(int)
b = -2 b = -2
try: try:
writeln(stdout, b - a) writeLine(stdout, b - a)
except OverflowError: except OverflowError:
writeln(stdout, "the computation overflowed") writeLine(stdout, "the computation overflowed")
{.pop.} # overflow check {.pop.} # overflow check
#OUT the computation overflowed #OUT the computation overflowed

View file

@ -58,7 +58,7 @@ for x in low(TAZ) .. high(TAZ):
for x in low(TTokTypeRange) .. high(TTokTypeRange): for x in low(TTokTypeRange) .. high(TTokTypeRange):
if x in tokTypes: if x in tokTypes:
discard discard
#writeln(stdout, "the token '$1' is in the set" % repr(x)) #writeLine(stdout, "the token '$1' is in the set" % repr(x))
#OUT Ha ein F ist in s! #OUT Ha ein F ist in s!

View file

@ -2,6 +2,6 @@
proc main() = proc main() =
for line in lines("thello.nim"): for line in lines("thello.nim"):
writeln(stdout, line) writeLine(stdout, line)
main() main()

View file

@ -3,24 +3,24 @@
import import
parseopt parseopt
proc writeHelp() = proc writeHelp() =
writeln(stdout, "Usage: tparsopt [options] filename [options]") writeLine(stdout, "Usage: tparsopt [options] filename [options]")
proc writeVersion() =
writeLine(stdout, "Version: 1.0.0")
proc writeVersion() =
writeln(stdout, "Version: 1.0.0")
var var
filename = "" filename = ""
for kind, key, val in getopt(): for kind, key, val in getopt():
case kind case kind
of cmdArgument: of cmdArgument:
filename = key filename = key
of cmdLongOption, cmdShortOption: of cmdLongOption, cmdShortOption:
case key case key
of "help", "h": writeHelp() of "help", "h": writeHelp()
of "version", "v": writeVersion() of "version", "v": writeVersion()
else: else:
writeln(stdout, "Unknown command line option: ", key, ": ", val) writeLine(stdout, "Unknown command line option: ", key, ": ", val)
of cmdEnd: assert(false) # cannot happen of cmdEnd: assert(false) # cannot happen
if filename == "": if filename == "":
# no filename has been given, so we show the help: # no filename has been given, so we show the help:

View file

@ -24,7 +24,7 @@ when useUnicode:
const const
InlineThreshold = 5 ## number of leaves; -1 to disable inlining InlineThreshold = 5 ## number of leaves; -1 to disable inlining
MaxSubpatterns* = 10 ## defines the maximum number of subpatterns that MaxSubpatterns* = 10 ## defines the maximum number of subpatterns that
## can be captured. More subpatterns cannot be captured! ## can be captured. More subpatterns cannot be captured!
type type
TPegKind = enum TPegKind = enum
@ -80,12 +80,12 @@ type
of pkBackRef..pkBackRefIgnoreStyle: index: range[0..MaxSubpatterns] of pkBackRef..pkBackRefIgnoreStyle: index: range[0..MaxSubpatterns]
else: sons: seq[TNode] else: sons: seq[TNode]
PNonTerminal* = ref TNonTerminal PNonTerminal* = ref TNonTerminal
TPeg* = TNode ## type that represents a PEG TPeg* = TNode ## type that represents a PEG
proc term*(t: string): TPeg {.rtl, extern: "npegs$1Str".} = proc term*(t: string): TPeg {.rtl, extern: "npegs$1Str".} =
## constructs a PEG from a terminal string ## constructs a PEG from a terminal string
if t.len != 1: if t.len != 1:
result.kind = pkTerminal result.kind = pkTerminal
result.term = t result.term = t
else: else:
@ -109,7 +109,7 @@ proc term*(t: char): TPeg {.rtl, extern: "npegs$1Char".} =
assert t != '\0' assert t != '\0'
result.kind = pkChar result.kind = pkChar
result.ch = t result.ch = t
proc charSet*(s: set[char]): TPeg {.rtl, extern: "npegs$1".} = proc charSet*(s: set[char]): TPeg {.rtl, extern: "npegs$1".} =
## constructs a PEG from a character set `s` ## constructs a PEG from a character set `s`
assert '\0' notin s assert '\0' notin s
@ -120,31 +120,31 @@ proc charSet*(s: set[char]): TPeg {.rtl, extern: "npegs$1".} =
proc len(a: TPeg): int {.inline.} = return a.sons.len proc len(a: TPeg): int {.inline.} = return a.sons.len
proc add(d: var TPeg, s: TPeg) {.inline.} = add(d.sons, s) proc add(d: var TPeg, s: TPeg) {.inline.} = add(d.sons, s)
proc copyPeg(a: TPeg): TPeg = proc copyPeg(a: TPeg): TPeg =
result.kind = a.kind result.kind = a.kind
case a.kind case a.kind
of pkEmpty..pkWhitespace: discard of pkEmpty..pkWhitespace: discard
of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle:
result.term = a.term result.term = a.term
of pkChar, pkGreedyRepChar: of pkChar, pkGreedyRepChar:
result.ch = a.ch result.ch = a.ch
of pkCharChoice, pkGreedyRepSet: of pkCharChoice, pkGreedyRepSet:
new(result.charChoice) new(result.charChoice)
result.charChoice[] = a.charChoice[] result.charChoice[] = a.charChoice[]
of pkNonTerminal: result.nt = a.nt of pkNonTerminal: result.nt = a.nt
of pkBackRef..pkBackRefIgnoreStyle: of pkBackRef..pkBackRefIgnoreStyle:
result.index = a.index result.index = a.index
else: else:
result.sons = a.sons result.sons = a.sons
proc addChoice(dest: var TPeg, elem: TPeg) = proc addChoice(dest: var TPeg, elem: TPeg) =
var L = dest.len-1 var L = dest.len-1
if L >= 0 and dest.sons[L].kind == pkCharChoice: if L >= 0 and dest.sons[L].kind == pkCharChoice:
# caution! Do not introduce false aliasing here! # caution! Do not introduce false aliasing here!
case elem.kind case elem.kind
of pkCharChoice: of pkCharChoice:
dest.sons[L] = charSet(dest.sons[L].charChoice[] + elem.charChoice[]) dest.sons[L] = charSet(dest.sons[L].charChoice[] + elem.charChoice[])
of pkChar: of pkChar:
dest.sons[L] = charSet(dest.sons[L].charChoice[] + {elem.ch}) dest.sons[L] = charSet(dest.sons[L].charChoice[] + {elem.ch})
else: add(dest, elem) else: add(dest, elem)
else: add(dest, elem) else: add(dest, elem)
@ -168,12 +168,12 @@ proc `/`*(a: varargs[TPeg]): TPeg {.
proc addSequence(dest: var TPeg, elem: TPeg) = proc addSequence(dest: var TPeg, elem: TPeg) =
var L = dest.len-1 var L = dest.len-1
if L >= 0 and dest.sons[L].kind == pkTerminal: if L >= 0 and dest.sons[L].kind == pkTerminal:
# caution! Do not introduce false aliasing here! # caution! Do not introduce false aliasing here!
case elem.kind case elem.kind
of pkTerminal: of pkTerminal:
dest.sons[L] = term(dest.sons[L].term & elem.term) dest.sons[L] = term(dest.sons[L].term & elem.term)
of pkChar: of pkChar:
dest.sons[L] = term(dest.sons[L].term & elem.ch) dest.sons[L] = term(dest.sons[L].term & elem.ch)
else: add(dest, elem) else: add(dest, elem)
else: add(dest, elem) else: add(dest, elem)
@ -182,7 +182,7 @@ proc sequence*(a: varargs[TPeg]): TPeg {.
rtl, extern: "npegs$1".} = rtl, extern: "npegs$1".} =
## constructs a sequence with all the PEGs from `a` ## constructs a sequence with all the PEGs from `a`
multipleOp(pkSequence, addSequence) multipleOp(pkSequence, addSequence)
proc `?`*(a: TPeg): TPeg {.rtl, extern: "npegsOptional".} = proc `?`*(a: TPeg): TPeg {.rtl, extern: "npegsOptional".} =
## constructs an optional for the PEG `a` ## constructs an optional for the PEG `a`
if a.kind in {pkOption, pkGreedyRep, pkGreedyAny, pkGreedyRepChar, if a.kind in {pkOption, pkGreedyRep, pkGreedyAny, pkGreedyRepChar,
@ -217,12 +217,12 @@ proc `!*`*(a: TPeg): TPeg {.rtl, extern: "npegsSearch".} =
result.kind = pkSearch result.kind = pkSearch
result.sons = @[a] result.sons = @[a]
proc `!*\`*(a: TPeg): TPeg {.rtl, proc `!*\`*(a: TPeg): TPeg {.rtl,
extern: "npgegsCapturedSearch".} = extern: "npgegsCapturedSearch".} =
## constructs a "captured search" for the PEG `a` ## constructs a "captured search" for the PEG `a`
result.kind = pkCapturedSearch result.kind = pkCapturedSearch
result.sons = @[a] result.sons = @[a]
when false: when false:
proc contains(a: TPeg, k: TPegKind): bool = proc contains(a: TPeg, k: TPegKind): bool =
if a.kind == k: return true if a.kind == k: return true
@ -238,7 +238,7 @@ when false:
proc `+`*(a: TPeg): TPeg {.rtl, extern: "npegsGreedyPosRep".} = proc `+`*(a: TPeg): TPeg {.rtl, extern: "npegsGreedyPosRep".} =
## constructs a "greedy positive repetition" with the PEG `a` ## constructs a "greedy positive repetition" with the PEG `a`
return sequence(a, *a) return sequence(a, *a)
proc `&`*(a: TPeg): TPeg {.rtl, extern: "npegsAndPredicate".} = proc `&`*(a: TPeg): TPeg {.rtl, extern: "npegsAndPredicate".} =
## constructs an "and predicate" with the PEG `a` ## constructs an "and predicate" with the PEG `a`
result.kind = pkAndPredicate result.kind = pkAndPredicate
@ -261,33 +261,33 @@ proc newLine*: TPeg {.inline.} =
## constructs the PEG `newline`:idx: (``\n``) ## constructs the PEG `newline`:idx: (``\n``)
result.kind = pkNewline result.kind = pkNewline
proc UnicodeLetter*: TPeg {.inline.} = proc UnicodeLetter*: TPeg {.inline.} =
## constructs the PEG ``\letter`` which matches any Unicode letter. ## constructs the PEG ``\letter`` which matches any Unicode letter.
result.kind = pkLetter result.kind = pkLetter
proc UnicodeLower*: TPeg {.inline.} =
## constructs the PEG ``\lower`` which matches any Unicode lowercase letter.
result.kind = pkLower
proc UnicodeUpper*: TPeg {.inline.} = proc UnicodeLower*: TPeg {.inline.} =
## constructs the PEG ``\lower`` which matches any Unicode lowercase letter.
result.kind = pkLower
proc UnicodeUpper*: TPeg {.inline.} =
## constructs the PEG ``\upper`` which matches any Unicode lowercase letter. ## constructs the PEG ``\upper`` which matches any Unicode lowercase letter.
result.kind = pkUpper result.kind = pkUpper
proc UnicodeTitle*: TPeg {.inline.} = proc UnicodeTitle*: TPeg {.inline.} =
## constructs the PEG ``\title`` which matches any Unicode title letter. ## constructs the PEG ``\title`` which matches any Unicode title letter.
result.kind = pkTitle result.kind = pkTitle
proc UnicodeWhitespace*: TPeg {.inline.} = proc UnicodeWhitespace*: TPeg {.inline.} =
## constructs the PEG ``\white`` which matches any Unicode ## constructs the PEG ``\white`` which matches any Unicode
## whitespace character. ## whitespace character.
result.kind = pkWhitespace result.kind = pkWhitespace
proc startAnchor*: TPeg {.inline.} = proc startAnchor*: TPeg {.inline.} =
## constructs the PEG ``^`` which matches the start of the input. ## constructs the PEG ``^`` which matches the start of the input.
result.kind = pkStartAnchor result.kind = pkStartAnchor
proc endAnchor*: TPeg {.inline.} = proc endAnchor*: TPeg {.inline.} =
## constructs the PEG ``$`` which matches the end of the input. ## constructs the PEG ``$`` which matches the end of the input.
result = !any() result = !any()
proc capture*(a: TPeg): TPeg {.rtl, extern: "npegsCapture".} = proc capture*(a: TPeg): TPeg {.rtl, extern: "npegsCapture".} =
@ -296,21 +296,21 @@ proc capture*(a: TPeg): TPeg {.rtl, extern: "npegsCapture".} =
result.sons = @[a] result.sons = @[a]
proc backref*(index: range[1..MaxSubPatterns]): TPeg {. proc backref*(index: range[1..MaxSubPatterns]): TPeg {.
rtl, extern: "npegs$1".} = rtl, extern: "npegs$1".} =
## constructs a back reference of the given `index`. `index` starts counting ## constructs a back reference of the given `index`. `index` starts counting
## from 1. ## from 1.
result.kind = pkBackRef result.kind = pkBackRef
result.index = index-1 result.index = index-1
proc backrefIgnoreCase*(index: range[1..MaxSubPatterns]): TPeg {. proc backrefIgnoreCase*(index: range[1..MaxSubPatterns]): TPeg {.
rtl, extern: "npegs$1".} = rtl, extern: "npegs$1".} =
## constructs a back reference of the given `index`. `index` starts counting ## constructs a back reference of the given `index`. `index` starts counting
## from 1. Ignores case for matching. ## from 1. Ignores case for matching.
result.kind = pkBackRefIgnoreCase result.kind = pkBackRefIgnoreCase
result.index = index-1 result.index = index-1
proc backrefIgnoreStyle*(index: range[1..MaxSubPatterns]): TPeg {. proc backrefIgnoreStyle*(index: range[1..MaxSubPatterns]): TPeg {.
rtl, extern: "npegs$1".}= rtl, extern: "npegs$1".}=
## constructs a back reference of the given `index`. `index` starts counting ## constructs a back reference of the given `index`. `index` starts counting
## from 1. Ignores style for matching. ## from 1. Ignores style for matching.
result.kind = pkBackRefIgnoreStyle result.kind = pkBackRefIgnoreStyle
@ -320,7 +320,7 @@ proc spaceCost(n: TPeg): int =
case n.kind case n.kind
of pkEmpty: discard of pkEmpty: discard
of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar, of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar,
pkGreedyRepChar, pkCharChoice, pkGreedyRepSet, pkGreedyRepChar, pkCharChoice, pkGreedyRepSet,
pkAny..pkWhitespace, pkGreedyAny: pkAny..pkWhitespace, pkGreedyAny:
result = 1 result = 1
of pkNonTerminal: of pkNonTerminal:
@ -332,7 +332,7 @@ proc spaceCost(n: TPeg): int =
if result >= InlineThreshold: break if result >= InlineThreshold: break
proc nonterminal*(n: PNonTerminal): TPeg {. proc nonterminal*(n: PNonTerminal): TPeg {.
rtl, extern: "npegs$1".} = rtl, extern: "npegs$1".} =
## constructs a PEG that consists of the nonterminal symbol ## constructs a PEG that consists of the nonterminal symbol
assert n != nil assert n != nil
if ntDeclared in n.flags and spaceCost(n.rule) < InlineThreshold: if ntDeclared in n.flags and spaceCost(n.rule) < InlineThreshold:
@ -353,7 +353,7 @@ proc newNonTerminal*(name: string, line, column: int): PNonTerminal {.
template letters*: expr = template letters*: expr =
## expands to ``charset({'A'..'Z', 'a'..'z'})`` ## expands to ``charset({'A'..'Z', 'a'..'z'})``
charset({'A'..'Z', 'a'..'z'}) charset({'A'..'Z', 'a'..'z'})
template digits*: expr = template digits*: expr =
## expands to ``charset({'0'..'9'})`` ## expands to ``charset({'0'..'9'})``
charset({'0'..'9'}) charset({'0'..'9'})
@ -361,11 +361,11 @@ template digits*: expr =
template whitespace*: expr = template whitespace*: expr =
## expands to ``charset({' ', '\9'..'\13'})`` ## expands to ``charset({' ', '\9'..'\13'})``
charset({' ', '\9'..'\13'}) charset({' ', '\9'..'\13'})
template identChars*: expr = template identChars*: expr =
## expands to ``charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})`` ## expands to ``charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})``
charset({'a'..'z', 'A'..'Z', '0'..'9', '_'}) charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})
template identStartChars*: expr = template identStartChars*: expr =
## expands to ``charset({'A'..'Z', 'a'..'z', '_'})`` ## expands to ``charset({'A'..'Z', 'a'..'z', '_'})``
charset({'a'..'z', 'A'..'Z', '_'}) charset({'a'..'z', 'A'..'Z', '_'})
@ -374,14 +374,14 @@ template ident*: expr =
## same as ``[a-zA-Z_][a-zA-z_0-9]*``; standard identifier ## same as ``[a-zA-Z_][a-zA-z_0-9]*``; standard identifier
sequence(charset({'a'..'z', 'A'..'Z', '_'}), sequence(charset({'a'..'z', 'A'..'Z', '_'}),
*charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})) *charset({'a'..'z', 'A'..'Z', '0'..'9', '_'}))
template natural*: expr = template natural*: expr =
## same as ``\d+`` ## same as ``\d+``
+digits +digits
# ------------------------- debugging ----------------------------------------- # ------------------------- debugging -----------------------------------------
proc esc(c: char, reserved = {'\0'..'\255'}): string = proc esc(c: char, reserved = {'\0'..'\255'}): string =
case c case c
of '\b': result = "\\b" of '\b': result = "\\b"
of '\t': result = "\\t" of '\t': result = "\\t"
@ -396,38 +396,38 @@ proc esc(c: char, reserved = {'\0'..'\255'}): string =
elif c < ' ' or c >= '\128': result = '\\' & $ord(c) elif c < ' ' or c >= '\128': result = '\\' & $ord(c)
elif c in reserved: result = '\\' & c elif c in reserved: result = '\\' & c
else: result = $c else: result = $c
proc singleQuoteEsc(c: char): string = return "'" & esc(c, {'\''}) & "'" proc singleQuoteEsc(c: char): string = return "'" & esc(c, {'\''}) & "'"
proc singleQuoteEsc(str: string): string = proc singleQuoteEsc(str: string): string =
result = "'" result = "'"
for c in items(str): add result, esc(c, {'\''}) for c in items(str): add result, esc(c, {'\''})
add result, '\'' add result, '\''
proc charSetEscAux(cc: set[char]): string = proc charSetEscAux(cc: set[char]): string =
const reserved = {'^', '-', ']'} const reserved = {'^', '-', ']'}
result = "" result = ""
var c1 = 0 var c1 = 0
while c1 <= 0xff: while c1 <= 0xff:
if chr(c1) in cc: if chr(c1) in cc:
var c2 = c1 var c2 = c1
while c2 < 0xff and chr(succ(c2)) in cc: inc(c2) while c2 < 0xff and chr(succ(c2)) in cc: inc(c2)
if c1 == c2: if c1 == c2:
add result, esc(chr(c1), reserved) add result, esc(chr(c1), reserved)
elif c2 == succ(c1): elif c2 == succ(c1):
add result, esc(chr(c1), reserved) & esc(chr(c2), reserved) add result, esc(chr(c1), reserved) & esc(chr(c2), reserved)
else: else:
add result, esc(chr(c1), reserved) & '-' & esc(chr(c2), reserved) add result, esc(chr(c1), reserved) & '-' & esc(chr(c2), reserved)
c1 = c2 c1 = c2
inc(c1) inc(c1)
proc charSetEsc(cc: set[char]): string = proc charSetEsc(cc: set[char]): string =
if card(cc) >= 128+64: if card(cc) >= 128+64:
result = "[^" & charSetEscAux({'\1'..'\xFF'} - cc) & ']' result = "[^" & charSetEscAux({'\1'..'\xFF'} - cc) & ']'
else: else:
result = '[' & charSetEscAux(cc) & ']' result = '[' & charSetEscAux(cc) & ']'
proc toStrAux(r: TPeg, res: var string) = proc toStrAux(r: TPeg, res: var string) =
case r.kind case r.kind
of pkEmpty: add(res, "()") of pkEmpty: add(res, "()")
of pkAny: add(res, '.') of pkAny: add(res, '.')
@ -491,25 +491,25 @@ proc toStrAux(r: TPeg, res: var string) =
toStrAux(r.sons[0], res) toStrAux(r.sons[0], res)
of pkCapture: of pkCapture:
add(res, '{') add(res, '{')
toStrAux(r.sons[0], res) toStrAux(r.sons[0], res)
add(res, '}') add(res, '}')
of pkBackRef: of pkBackRef:
add(res, '$') add(res, '$')
add(res, $r.index) add(res, $r.index)
of pkBackRefIgnoreCase: of pkBackRefIgnoreCase:
add(res, "i$") add(res, "i$")
add(res, $r.index) add(res, $r.index)
of pkBackRefIgnoreStyle: of pkBackRefIgnoreStyle:
add(res, "y$") add(res, "y$")
add(res, $r.index) add(res, $r.index)
of pkRule: of pkRule:
toStrAux(r.sons[0], res) toStrAux(r.sons[0], res)
add(res, " <- ") add(res, " <- ")
toStrAux(r.sons[1], res) toStrAux(r.sons[1], res)
of pkList: of pkList:
for i in 0 .. high(r.sons): for i in 0 .. high(r.sons):
toStrAux(r.sons[i], res) toStrAux(r.sons[i], res)
add(res, "\n") add(res, "\n")
of pkStartAnchor: of pkStartAnchor:
add(res, '^') add(res, '^')
@ -526,8 +526,8 @@ type
ml: int ml: int
origStart: int origStart: int
proc bounds*(c: TCaptures, proc bounds*(c: TCaptures,
i: range[0..MaxSubpatterns-1]): tuple[first, last: int] = i: range[0..MaxSubpatterns-1]): tuple[first, last: int] =
## returns the bounds ``[first..last]`` of the `i`'th capture. ## returns the bounds ``[first..last]`` of the `i`'th capture.
result = c.matches[i] result = c.matches[i]
@ -547,7 +547,7 @@ when not useUnicode:
proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {. proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
rtl, extern: "npegs$1".} = rtl, extern: "npegs$1".} =
## low-level matching proc that implements the PEG interpreter. Use this ## low-level matching proc that implements the PEG interpreter. Use this
## for maximum efficiency (every other PEG operation ends up calling this ## for maximum efficiency (every other PEG operation ends up calling this
## proc). ## proc).
## Returns -1 if it does not match, else the length of the match ## Returns -1 if it does not match, else the length of the match
@ -561,7 +561,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
result = runeLenAt(s, start) result = runeLenAt(s, start)
else: else:
result = -1 result = -1
of pkLetter: of pkLetter:
if s[start] != '\0': if s[start] != '\0':
var a: Rune var a: Rune
result = start result = start
@ -570,7 +570,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
else: result = -1 else: result = -1
else: else:
result = -1 result = -1
of pkLower: of pkLower:
if s[start] != '\0': if s[start] != '\0':
var a: Rune var a: Rune
result = start result = start
@ -579,7 +579,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
else: result = -1 else: result = -1
else: else:
result = -1 result = -1
of pkUpper: of pkUpper:
if s[start] != '\0': if s[start] != '\0':
var a: Rune var a: Rune
result = start result = start
@ -588,16 +588,16 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
else: result = -1 else: result = -1
else: else:
result = -1 result = -1
of pkTitle: of pkTitle:
if s[start] != '\0': if s[start] != '\0':
var a: Rune var a: Rune
result = start result = start
fastRuneAt(s, result, a) fastRuneAt(s, result, a)
if isTitle(a): dec(result, start) if isTitle(a): dec(result, start)
else: result = -1 else: result = -1
else: else:
result = -1 result = -1
of pkWhitespace: of pkWhitespace:
if s[start] != '\0': if s[start] != '\0':
var a: Rune var a: Rune
result = start result = start
@ -661,7 +661,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
when false: echo "leave: ", p.nt.name when false: echo "leave: ", p.nt.name
if result < 0: c.ml = oldMl if result < 0: c.ml = oldMl
of pkSequence: of pkSequence:
var oldMl = c.ml var oldMl = c.ml
result = 0 result = 0
assert(not isNil(p.sons)) assert(not isNil(p.sons))
for i in 0..high(p.sons): for i in 0..high(p.sons):
@ -744,11 +744,11 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
#else: silently ignore the capture #else: silently ignore the capture
else: else:
c.ml = idx c.ml = idx
of pkBackRef..pkBackRefIgnoreStyle: of pkBackRef..pkBackRefIgnoreStyle:
if p.index >= c.ml: return -1 if p.index >= c.ml: return -1
var (a, b) = c.matches[p.index] var (a, b) = c.matches[p.index]
var n: TPeg var n: TPeg
n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef)) n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef))
n.term = s.substr(a, b) n.term = s.substr(a, b)
result = rawMatch(s, n, start, c) result = rawMatch(s, n, start, c)
of pkStartAnchor: of pkStartAnchor:
@ -769,7 +769,7 @@ proc match*(s: string, pattern: TPeg, matches: var openarray[string],
for i in 0..c.ml-1: for i in 0..c.ml-1:
matches[i] = substr(s, c.matches[i][0], c.matches[i][1]) matches[i] = substr(s, c.matches[i][0], c.matches[i][1])
proc match*(s: string, pattern: TPeg, proc match*(s: string, pattern: TPeg,
start = 0): bool {.rtl, extern: "npegs$1".} = start = 0): bool {.rtl, extern: "npegs$1".} =
## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``. ## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``.
var c: TCaptures var c: TCaptures
@ -789,7 +789,7 @@ proc matchLen*(s: string, pattern: TPeg, matches: var openarray[string],
for i in 0..c.ml-1: for i in 0..c.ml-1:
matches[i] = substr(s, c.matches[i][0], c.matches[i][1]) matches[i] = substr(s, c.matches[i][0], c.matches[i][1])
proc matchLen*(s: string, pattern: TPeg, proc matchLen*(s: string, pattern: TPeg,
start = 0): int {.rtl, extern: "npegs$1".} = start = 0): int {.rtl, extern: "npegs$1".} =
## the same as ``match``, but it returns the length of the match, ## the same as ``match``, but it returns the length of the match,
## if there is no match, -1 is returned. Note that a match length ## if there is no match, -1 is returned. Note that a match length
@ -808,11 +808,11 @@ proc find*(s: string, pattern: TPeg, matches: var openarray[string],
if matchLen(s, pattern, matches, i) >= 0: return i if matchLen(s, pattern, matches, i) >= 0: return i
return -1 return -1
# could also use the pattern here: (!P .)* P # could also use the pattern here: (!P .)* P
proc findBounds*(s: string, pattern: TPeg, matches: var openarray[string], proc findBounds*(s: string, pattern: TPeg, matches: var openarray[string],
start = 0): tuple[first, last: int] {. start = 0): tuple[first, last: int] {.
rtl, extern: "npegs$1Capture".} = rtl, extern: "npegs$1Capture".} =
## returns the starting position and end position of ``pattern`` in ``s`` ## returns the starting position and end position of ``pattern`` in ``s``
## and the captured ## and the captured
## substrings in the array ``matches``. If it does not match, nothing ## substrings in the array ``matches``. If it does not match, nothing
## is written into ``matches`` and (-1,0) is returned. ## is written into ``matches`` and (-1,0) is returned.
@ -820,40 +820,40 @@ proc findBounds*(s: string, pattern: TPeg, matches: var openarray[string],
var L = matchLen(s, pattern, matches, i) var L = matchLen(s, pattern, matches, i)
if L >= 0: return (i, i+L-1) if L >= 0: return (i, i+L-1)
return (-1, 0) return (-1, 0)
proc find*(s: string, pattern: TPeg, proc find*(s: string, pattern: TPeg,
start = 0): int {.rtl, extern: "npegs$1".} = start = 0): int {.rtl, extern: "npegs$1".} =
## returns the starting position of ``pattern`` in ``s``. If it does not ## returns the starting position of ``pattern`` in ``s``. If it does not
## match, -1 is returned. ## match, -1 is returned.
for i in start .. s.len-1: for i in start .. s.len-1:
if matchLen(s, pattern, i) >= 0: return i if matchLen(s, pattern, i) >= 0: return i
return -1 return -1
iterator findAll*(s: string, pattern: TPeg, start = 0): string = iterator findAll*(s: string, pattern: TPeg, start = 0): string =
## yields all matching captures of pattern in `s`. ## yields all matching captures of pattern in `s`.
var matches: array[0..MaxSubpatterns-1, string] var matches: array[0..MaxSubpatterns-1, string]
var i = start var i = start
while i < s.len: while i < s.len:
var L = matchLen(s, pattern, matches, i) var L = matchLen(s, pattern, matches, i)
if L < 0: break if L < 0: break
for k in 0..MaxSubPatterns-1: for k in 0..MaxSubPatterns-1:
if isNil(matches[k]): break if isNil(matches[k]): break
yield matches[k] yield matches[k]
inc(i, L) inc(i, L)
proc findAll*(s: string, pattern: TPeg, start = 0): seq[string] {. proc findAll*(s: string, pattern: TPeg, start = 0): seq[string] {.
rtl, extern: "npegs$1".} = rtl, extern: "npegs$1".} =
## returns all matching captures of pattern in `s`. ## returns all matching captures of pattern in `s`.
## If it does not match, @[] is returned. ## If it does not match, @[] is returned.
accumulateResult(findAll(s, pattern, start)) accumulateResult(findAll(s, pattern, start))
template `=~`*(s: string, pattern: TPeg): expr = template `=~`*(s: string, pattern: TPeg): expr =
## This calls ``match`` with an implicit declared ``matches`` array that ## This calls ``match`` with an implicit declared ``matches`` array that
## can be used in the scope of the ``=~`` call: ## can be used in the scope of the ``=~`` call:
## ##
## .. code-block:: nim ## .. code-block:: nim
## ##
## if line =~ peg"\s* {\w+} \s* '=' \s* {\w+}": ## if line =~ peg"\s* {\w+} \s* '=' \s* {\w+}":
## # matches a key=value pair: ## # matches a key=value pair:
## echo("Key: ", matches[0]) ## echo("Key: ", matches[0])
## echo("Value: ", matches[1]) ## echo("Value: ", matches[1])
@ -864,7 +864,7 @@ template `=~`*(s: string, pattern: TPeg): expr =
## echo("comment: ", matches[0]) ## echo("comment: ", matches[0])
## else: ## else:
## echo("syntax error") ## echo("syntax error")
## ##
when not declaredInScope(matches): when not declaredInScope(matches):
var matches {.inject.}: array[0..MaxSubpatterns-1, string] var matches {.inject.}: array[0..MaxSubpatterns-1, string]
match(s, pattern, matches) match(s, pattern, matches)
@ -934,10 +934,10 @@ proc replace*(s: string, sub: TPeg, by = ""): string {.
addf(result, by, caps) addf(result, by, caps)
inc(i, x) inc(i, x)
add(result, substr(s, i)) add(result, substr(s, i))
proc parallelReplace*(s: string, subs: varargs[ proc parallelReplace*(s: string, subs: varargs[
tuple[pattern: TPeg, repl: string]]): string {. tuple[pattern: TPeg, repl: string]]): string {.
rtl, extern: "npegs$1".} = rtl, extern: "npegs$1".} =
## Returns a modified copy of `s` with the substitutions in `subs` ## Returns a modified copy of `s` with the substitutions in `subs`
## applied in parallel. ## applied in parallel.
result = "" result = ""
@ -954,8 +954,8 @@ proc parallelReplace*(s: string, subs: varargs[
add(result, s[i]) add(result, s[i])
inc(i) inc(i)
# copy the rest: # copy the rest:
add(result, substr(s, i)) add(result, substr(s, i))
proc transformFile*(infile, outfile: string, proc transformFile*(infile, outfile: string,
subs: varargs[tuple[pattern: TPeg, repl: string]]) {. subs: varargs[tuple[pattern: TPeg, repl: string]]) {.
rtl, extern: "npegs$1".} = rtl, extern: "npegs$1".} =
@ -972,7 +972,7 @@ proc transformFile*(infile, outfile: string,
quit("cannot open for writing: " & outfile) quit("cannot open for writing: " & outfile)
else: else:
quit("cannot open for reading: " & infile) quit("cannot open for reading: " & infile)
iterator split*(s: string, sep: TPeg): string = iterator split*(s: string, sep: TPeg): string =
## Splits the string `s` into substrings. ## Splits the string `s` into substrings.
## ##
@ -981,7 +981,7 @@ iterator split*(s: string, sep: TPeg): string =
## ##
## .. code-block:: nim ## .. code-block:: nim
## for word in split("00232this02939is39an22example111", peg"\d+"): ## for word in split("00232this02939is39an22example111", peg"\d+"):
## writeln(stdout, word) ## writeLine(stdout, word)
## ##
## Results in: ## Results in:
## ##
@ -1044,14 +1044,14 @@ type
tkBackref, ## '$' tkBackref, ## '$'
tkDollar, ## '$' tkDollar, ## '$'
tkHat ## '^' tkHat ## '^'
TToken {.final.} = object ## a token TToken {.final.} = object ## a token
kind: TTokKind ## the type of the token kind: TTokKind ## the type of the token
modifier: TModifier modifier: TModifier
literal: string ## the parsed (string) literal literal: string ## the parsed (string) literal
charset: set[char] ## if kind == tkCharSet charset: set[char] ## if kind == tkCharSet
index: int ## if kind == tkBackref index: int ## if kind == tkBackref
TPegLexer {.inheritable.} = object ## the lexer object. TPegLexer {.inheritable.} = object ## the lexer object.
bufpos: int ## the current position within the buffer bufpos: int ## the current position within the buffer
buf: cstring ## the buffer itself buf: cstring ## the buffer itself
@ -1081,7 +1081,7 @@ proc HandleLF(L: var TPegLexer, pos: int): int =
result = pos+1 result = pos+1
L.lineStart = result L.lineStart = result
proc init(L: var TPegLexer, input, filename: string, line = 1, col = 0) = proc init(L: var TPegLexer, input, filename: string, line = 1, col = 0) =
L.buf = input L.buf = input
L.bufpos = 0 L.bufpos = 0
L.lineNumber = line L.lineNumber = line
@ -1089,69 +1089,69 @@ proc init(L: var TPegLexer, input, filename: string, line = 1, col = 0) =
L.lineStart = 0 L.lineStart = 0
L.filename = filename L.filename = filename
proc getColumn(L: TPegLexer): int {.inline.} = proc getColumn(L: TPegLexer): int {.inline.} =
result = abs(L.bufpos - L.lineStart) + L.colOffset result = abs(L.bufpos - L.lineStart) + L.colOffset
proc getLine(L: TPegLexer): int {.inline.} = proc getLine(L: TPegLexer): int {.inline.} =
result = L.linenumber result = L.linenumber
proc errorStr(L: TPegLexer, msg: string, line = -1, col = -1): string = proc errorStr(L: TPegLexer, msg: string, line = -1, col = -1): string =
var line = if line < 0: getLine(L) else: line var line = if line < 0: getLine(L) else: line
var col = if col < 0: getColumn(L) else: col var col = if col < 0: getColumn(L) else: col
result = "$1($2, $3) Error: $4" % [L.filename, $line, $col, msg] result = "$1($2, $3) Error: $4" % [L.filename, $line, $col, msg]
proc handleHexChar(c: var TPegLexer, xi: var int) = proc handleHexChar(c: var TPegLexer, xi: var int) =
case c.buf[c.bufpos] case c.buf[c.bufpos]
of '0'..'9': of '0'..'9':
xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0')) xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0'))
inc(c.bufpos) inc(c.bufpos)
of 'a'..'f': of 'a'..'f':
xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10) xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10)
inc(c.bufpos) inc(c.bufpos)
of 'A'..'F': of 'A'..'F':
xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10) xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
inc(c.bufpos) inc(c.bufpos)
else: discard else: discard
proc getEscapedChar(c: var TPegLexer, tok: var TToken) = proc getEscapedChar(c: var TPegLexer, tok: var TToken) =
inc(c.bufpos) inc(c.bufpos)
case c.buf[c.bufpos] case c.buf[c.bufpos]
of 'r', 'R', 'c', 'C': of 'r', 'R', 'c', 'C':
add(tok.literal, '\c') add(tok.literal, '\c')
inc(c.bufpos) inc(c.bufpos)
of 'l', 'L': of 'l', 'L':
add(tok.literal, '\L') add(tok.literal, '\L')
inc(c.bufpos) inc(c.bufpos)
of 'f', 'F': of 'f', 'F':
add(tok.literal, '\f') add(tok.literal, '\f')
inc(c.bufpos) inc(c.bufpos)
of 'e', 'E': of 'e', 'E':
add(tok.literal, '\e') add(tok.literal, '\e')
inc(c.bufpos) inc(c.bufpos)
of 'a', 'A': of 'a', 'A':
add(tok.literal, '\a') add(tok.literal, '\a')
inc(c.bufpos) inc(c.bufpos)
of 'b', 'B': of 'b', 'B':
add(tok.literal, '\b') add(tok.literal, '\b')
inc(c.bufpos) inc(c.bufpos)
of 'v', 'V': of 'v', 'V':
add(tok.literal, '\v') add(tok.literal, '\v')
inc(c.bufpos) inc(c.bufpos)
of 't', 'T': of 't', 'T':
add(tok.literal, '\t') add(tok.literal, '\t')
inc(c.bufpos) inc(c.bufpos)
of 'x', 'X': of 'x', 'X':
inc(c.bufpos) inc(c.bufpos)
var xi = 0 var xi = 0
handleHexChar(c, xi) handleHexChar(c, xi)
handleHexChar(c, xi) handleHexChar(c, xi)
if xi == 0: tok.kind = tkInvalid if xi == 0: tok.kind = tkInvalid
else: add(tok.literal, chr(xi)) else: add(tok.literal, chr(xi))
of '0'..'9': of '0'..'9':
var val = ord(c.buf[c.bufpos]) - ord('0') var val = ord(c.buf[c.bufpos]) - ord('0')
inc(c.bufpos) inc(c.bufpos)
var i = 1 var i = 1
while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}): while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}):
val = val * 10 + ord(c.buf[c.bufpos]) - ord('0') val = val * 10 + ord(c.buf[c.bufpos]) - ord('0')
inc(c.bufpos) inc(c.bufpos)
inc(i) inc(i)
@ -1164,32 +1164,32 @@ proc getEscapedChar(c: var TPegLexer, tok: var TToken) =
else: else:
add(tok.literal, c.buf[c.bufpos]) add(tok.literal, c.buf[c.bufpos])
inc(c.bufpos) inc(c.bufpos)
proc skip(c: var TPegLexer) = proc skip(c: var TPegLexer) =
var pos = c.bufpos var pos = c.bufpos
var buf = c.buf var buf = c.buf
while true: while true:
case buf[pos] case buf[pos]
of ' ', '\t': of ' ', '\t':
inc(pos) inc(pos)
of '#': of '#':
while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos) while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
of '\c': of '\c':
pos = HandleCR(c, pos) pos = HandleCR(c, pos)
buf = c.buf buf = c.buf
of '\L': of '\L':
pos = HandleLF(c, pos) pos = HandleLF(c, pos)
buf = c.buf buf = c.buf
else: else:
break # EndOfFile also leaves the loop break # EndOfFile also leaves the loop
c.bufpos = pos c.bufpos = pos
proc getString(c: var TPegLexer, tok: var TToken) = proc getString(c: var TPegLexer, tok: var TToken) =
tok.kind = tkStringLit tok.kind = tkStringLit
var pos = c.bufPos + 1 var pos = c.bufPos + 1
var buf = c.buf var buf = c.buf
var quote = buf[pos-1] var quote = buf[pos-1]
while true: while true:
case buf[pos] case buf[pos]
of '\\': of '\\':
c.bufpos = pos c.bufpos = pos
@ -1200,13 +1200,13 @@ proc getString(c: var TPegLexer, tok: var TToken) =
break break
elif buf[pos] == quote: elif buf[pos] == quote:
inc(pos) inc(pos)
break break
else: else:
add(tok.literal, buf[pos]) add(tok.literal, buf[pos])
inc(pos) inc(pos)
c.bufpos = pos c.bufpos = pos
proc getDollar(c: var TPegLexer, tok: var TToken) = proc getDollar(c: var TPegLexer, tok: var TToken) =
var pos = c.bufPos + 1 var pos = c.bufPos + 1
var buf = c.buf var buf = c.buf
if buf[pos] in {'0'..'9'}: if buf[pos] in {'0'..'9'}:
@ -1218,8 +1218,8 @@ proc getDollar(c: var TPegLexer, tok: var TToken) =
else: else:
tok.kind = tkDollar tok.kind = tkDollar
c.bufpos = pos c.bufpos = pos
proc getCharSet(c: var TPegLexer, tok: var TToken) = proc getCharSet(c: var TPegLexer, tok: var TToken) =
tok.kind = tkCharSet tok.kind = tkCharSet
tok.charset = {} tok.charset = {}
var pos = c.bufPos + 1 var pos = c.bufPos + 1
@ -1242,7 +1242,7 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) =
of '\C', '\L', '\0': of '\C', '\L', '\0':
tok.kind = tkInvalid tok.kind = tkInvalid
break break
else: else:
ch = buf[pos] ch = buf[pos]
inc(pos) inc(pos)
incl(tok.charset, ch) incl(tok.charset, ch)
@ -1262,18 +1262,18 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) =
of '\C', '\L', '\0': of '\C', '\L', '\0':
tok.kind = tkInvalid tok.kind = tkInvalid
break break
else: else:
ch2 = buf[pos] ch2 = buf[pos]
inc(pos) inc(pos)
for i in ord(ch)+1 .. ord(ch2): for i in ord(ch)+1 .. ord(ch2):
incl(tok.charset, chr(i)) incl(tok.charset, chr(i))
c.bufpos = pos c.bufpos = pos
if caret: tok.charset = {'\1'..'\xFF'} - tok.charset if caret: tok.charset = {'\1'..'\xFF'} - tok.charset
proc getSymbol(c: var TPegLexer, tok: var TToken) = proc getSymbol(c: var TPegLexer, tok: var TToken) =
var pos = c.bufpos var pos = c.bufpos
var buf = c.buf var buf = c.buf
while true: while true:
add(tok.literal, buf[pos]) add(tok.literal, buf[pos])
inc(pos) inc(pos)
if buf[pos] notin strutils.IdentChars: break if buf[pos] notin strutils.IdentChars: break
@ -1289,7 +1289,7 @@ proc getBuiltin(c: var TPegLexer, tok: var TToken) =
tok.kind = tkEscaped tok.kind = tkEscaped
getEscapedChar(c, tok) # may set tok.kind to tkInvalid getEscapedChar(c, tok) # may set tok.kind to tkInvalid
proc getTok(c: var TPegLexer, tok: var TToken) = proc getTok(c: var TPegLexer, tok: var TToken) =
tok.kind = tkInvalid tok.kind = tkInvalid
tok.modifier = modNone tok.modifier = modNone
setlen(tok.literal, 0) setlen(tok.literal, 0)
@ -1304,11 +1304,11 @@ proc getTok(c: var TPegLexer, tok: var TToken) =
else: else:
tok.kind = tkCurlyLe tok.kind = tkCurlyLe
add(tok.literal, '{') add(tok.literal, '{')
of '}': of '}':
tok.kind = tkCurlyRi tok.kind = tkCurlyRi
inc(c.bufpos) inc(c.bufpos)
add(tok.literal, '}') add(tok.literal, '}')
of '[': of '[':
getCharset(c, tok) getCharset(c, tok)
of '(': of '(':
tok.kind = tkParLe tok.kind = tkParLe
@ -1318,7 +1318,7 @@ proc getTok(c: var TPegLexer, tok: var TToken) =
tok.kind = tkParRi tok.kind = tkParRi
inc(c.bufpos) inc(c.bufpos)
add(tok.literal, ')') add(tok.literal, ')')
of '.': of '.':
tok.kind = tkAny tok.kind = tkAny
inc(c.bufpos) inc(c.bufpos)
add(tok.literal, '.') add(tok.literal, '.')
@ -1326,16 +1326,16 @@ proc getTok(c: var TPegLexer, tok: var TToken) =
tok.kind = tkAnyRune tok.kind = tkAnyRune
inc(c.bufpos) inc(c.bufpos)
add(tok.literal, '_') add(tok.literal, '_')
of '\\': of '\\':
getBuiltin(c, tok) getBuiltin(c, tok)
of '\'', '"': getString(c, tok) of '\'', '"': getString(c, tok)
of '$': getDollar(c, tok) of '$': getDollar(c, tok)
of '\0': of '\0':
tok.kind = tkEof tok.kind = tkEof
tok.literal = "[EOF]" tok.literal = "[EOF]"
of 'a'..'z', 'A'..'Z', '\128'..'\255': of 'a'..'z', 'A'..'Z', '\128'..'\255':
getSymbol(c, tok) getSymbol(c, tok)
if c.buf[c.bufpos] in {'\'', '"'} or if c.buf[c.bufpos] in {'\'', '"'} or
c.buf[c.bufpos] == '$' and c.buf[c.bufpos+1] in {'0'..'9'}: c.buf[c.bufpos] == '$' and c.buf[c.bufpos+1] in {'0'..'9'}:
case tok.literal case tok.literal
of "i": tok.modifier = modIgnoreCase of "i": tok.modifier = modIgnoreCase
@ -1383,7 +1383,7 @@ proc getTok(c: var TPegLexer, tok: var TToken) =
tok.kind = tkAt tok.kind = tkAt
inc(c.bufpos) inc(c.bufpos)
add(tok.literal, '@') add(tok.literal, '@')
if c.buf[c.bufpos] == '@': if c.buf[c.bufpos] == '@':
tok.kind = tkCurlyAt tok.kind = tkCurlyAt
inc(c.bufpos) inc(c.bufpos)
add(tok.literal, '@') add(tok.literal, '@')
@ -1402,7 +1402,7 @@ proc arrowIsNextTok(c: TPegLexer): bool =
result = c.buf[pos] == '<' and c.buf[pos+1] == '-' result = c.buf[pos] == '<' and c.buf[pos+1] == '-'
# ----------------------------- parser ---------------------------------------- # ----------------------------- parser ----------------------------------------
type type
EInvalidPeg* = object of ValueError ## raised if an invalid EInvalidPeg* = object of ValueError ## raised if an invalid
## PEG has been detected ## PEG has been detected
@ -1420,7 +1420,7 @@ proc pegError(p: TPegParser, msg: string, line = -1, col = -1) =
e.msg = errorStr(p, msg, line, col) e.msg = errorStr(p, msg, line, col)
raise e raise e
proc getTok(p: var TPegParser) = proc getTok(p: var TPegParser) =
getTok(p, p.tok) getTok(p, p.tok)
if p.tok.kind == tkInvalid: pegError(p, "invalid token") if p.tok.kind == tkInvalid: pegError(p, "invalid token")
@ -1470,7 +1470,7 @@ proc builtin(p: var TPegParser): TPeg =
of "white": result = UnicodeWhitespace() of "white": result = UnicodeWhitespace()
else: pegError(p, "unknown built-in: " & p.tok.literal) else: pegError(p, "unknown built-in: " & p.tok.literal)
proc token(terminal: TPeg, p: TPegParser): TPeg = proc token(terminal: TPeg, p: TPegParser): TPeg =
if p.skip.kind == pkEmpty: result = terminal if p.skip.kind == pkEmpty: result = terminal
else: result = sequence(p.skip, terminal) else: result = sequence(p.skip, terminal)
@ -1491,7 +1491,7 @@ proc primary(p: var TPegParser): TPeg =
else: discard else: discard
case p.tok.kind case p.tok.kind
of tkIdentifier: of tkIdentifier:
if p.identIsVerbatim: if p.identIsVerbatim:
var m = p.tok.modifier var m = p.tok.modifier
if m == modNone: m = p.modifier if m == modNone: m = p.modifier
result = modifiedTerm(p.tok.literal, m).token(p) result = modifiedTerm(p.tok.literal, m).token(p)
@ -1534,17 +1534,17 @@ proc primary(p: var TPegParser): TPeg =
of tkEscaped: of tkEscaped:
result = term(p.tok.literal[0]).token(p) result = term(p.tok.literal[0]).token(p)
getTok(p) getTok(p)
of tkDollar: of tkDollar:
result = endAnchor() result = endAnchor()
getTok(p) getTok(p)
of tkHat: of tkHat:
result = startAnchor() result = startAnchor()
getTok(p) getTok(p)
of tkBackref: of tkBackref:
var m = p.tok.modifier var m = p.tok.modifier
if m == modNone: m = p.modifier if m == modNone: m = p.modifier
result = modifiedBackRef(p.tok.index, m).token(p) result = modifiedBackRef(p.tok.index, m).token(p)
if p.tok.index < 0 or p.tok.index > p.captures: if p.tok.index < 0 or p.tok.index > p.captures:
pegError(p, "invalid back reference index: " & $p.tok.index) pegError(p, "invalid back reference index: " & $p.tok.index)
getTok(p) getTok(p)
else: else:
@ -1568,7 +1568,7 @@ proc seqExpr(p: var TPegParser): TPeg =
while true: while true:
case p.tok.kind case p.tok.kind
of tkAmp, tkNot, tkAt, tkStringLit, tkCharset, tkParLe, tkCurlyLe, of tkAmp, tkNot, tkAt, tkStringLit, tkCharset, tkParLe, tkCurlyLe,
tkAny, tkAnyRune, tkBuiltin, tkEscaped, tkDollar, tkBackref, tkAny, tkAnyRune, tkBuiltin, tkEscaped, tkDollar, tkBackref,
tkHat, tkCurlyAt: tkHat, tkCurlyAt:
result = sequence(result, primary(p)) result = sequence(result, primary(p))
of tkIdentifier: of tkIdentifier:
@ -1582,7 +1582,7 @@ proc parseExpr(p: var TPegParser): TPeg =
while p.tok.kind == tkBar: while p.tok.kind == tkBar:
getTok(p) getTok(p)
result = result / seqExpr(p) result = result / seqExpr(p)
proc parseRule(p: var TPegParser): PNonTerminal = proc parseRule(p: var TPegParser): PNonTerminal =
if p.tok.kind == tkIdentifier and arrowIsNextTok(p): if p.tok.kind == tkIdentifier and arrowIsNextTok(p):
result = getNonTerminal(p, p.tok.literal) result = getNonTerminal(p, p.tok.literal)
@ -1596,7 +1596,7 @@ proc parseRule(p: var TPegParser): PNonTerminal =
incl(result.flags, ntDeclared) # NOW inlining may be attempted incl(result.flags, ntDeclared) # NOW inlining may be attempted
else: else:
pegError(p, "rule expected, but found: " & p.tok.literal) pegError(p, "rule expected, but found: " & p.tok.literal)
proc rawParse(p: var TPegParser): TPeg = proc rawParse(p: var TPegParser): TPeg =
## parses a rule or a PEG expression ## parses a rule or a PEG expression
while p.tok.kind == tkBuiltin: while p.tok.kind == tkBuiltin:
@ -1649,20 +1649,20 @@ proc peg*(pattern: string): TPeg =
## peg"{\ident} \s* '=' \s* {.*}" ## peg"{\ident} \s* '=' \s* {.*}"
result = parsePeg(pattern, "pattern") result = parsePeg(pattern, "pattern")
proc escapePeg*(s: string): string = proc escapePeg*(s: string): string =
## escapes `s` so that it is matched verbatim when used as a peg. ## escapes `s` so that it is matched verbatim when used as a peg.
result = "" result = ""
var inQuote = false var inQuote = false
for c in items(s): for c in items(s):
case c case c
of '\0'..'\31', '\'', '"', '\\': of '\0'..'\31', '\'', '"', '\\':
if inQuote: if inQuote:
result.add('\'') result.add('\'')
inQuote = false inQuote = false
result.add("\\x") result.add("\\x")
result.add(toHex(ord(c), 2)) result.add(toHex(ord(c), 2))
else: else:
if not inQuote: if not inQuote:
result.add('\'') result.add('\'')
inQuote = true inQuote = true
result.add(c) result.add(c)
@ -1675,27 +1675,27 @@ when isMainModule:
doAssert(not match("W_HI_L", peg"\y 'while'")) doAssert(not match("W_HI_L", peg"\y 'while'"))
doAssert(not match("W_HI_Le", peg"\y v'while'")) doAssert(not match("W_HI_Le", peg"\y v'while'"))
doAssert match("W_HI_Le", peg"y'while'") doAssert match("W_HI_Le", peg"y'while'")
doAssert($ +digits == $peg"\d+") doAssert($ +digits == $peg"\d+")
doAssert "0158787".match(peg"\d+") doAssert "0158787".match(peg"\d+")
doAssert "ABC 0232".match(peg"\w+\s+\d+") doAssert "ABC 0232".match(peg"\w+\s+\d+")
doAssert "ABC".match(peg"\d+ / \w+") doAssert "ABC".match(peg"\d+ / \w+")
for word in split("00232this02939is39an22example111", peg"\d+"): for word in split("00232this02939is39an22example111", peg"\d+"):
writeln(stdout, word) writeLine(stdout, word)
doAssert matchLen("key", ident) == 3 doAssert matchLen("key", ident) == 3
var pattern = sequence(ident, *whitespace, term('='), *whitespace, ident) var pattern = sequence(ident, *whitespace, term('='), *whitespace, ident)
doAssert matchLen("key1= cal9", pattern) == 11 doAssert matchLen("key1= cal9", pattern) == 11
var ws = newNonTerminal("ws", 1, 1) var ws = newNonTerminal("ws", 1, 1)
ws.rule = *whitespace ws.rule = *whitespace
var expr = newNonTerminal("expr", 1, 1) var expr = newNonTerminal("expr", 1, 1)
expr.rule = sequence(capture(ident), *sequence( expr.rule = sequence(capture(ident), *sequence(
nonterminal(ws), term('+'), nonterminal(ws), nonterminal(expr))) nonterminal(ws), term('+'), nonterminal(ws), nonterminal(expr)))
var c: TCaptures var c: TCaptures
var s = "a+b + c +d+e+f" var s = "a+b + c +d+e+f"
doAssert rawMatch(s, expr.rule, 0, c) == len(s) doAssert rawMatch(s, expr.rule, 0, c) == len(s)
@ -1716,7 +1716,7 @@ when isMainModule:
doAssert matches[0] == "abc" doAssert matches[0] == "abc"
else: else:
doAssert false doAssert false
var g2 = peg"""S <- A B / C D var g2 = peg"""S <- A B / C D
A <- 'a'+ A <- 'a'+
B <- 'b'+ B <- 'b'+
@ -1733,10 +1733,10 @@ when isMainModule:
doAssert matches[0] == "a" doAssert matches[0] == "a"
else: else:
doAssert false doAssert false
block: block:
var matches: array[0..2, string] var matches: array[0..2, string]
if match("abcdefg", peg"c {d} ef {g}", matches, 2): if match("abcdefg", peg"c {d} ef {g}", matches, 2):
doAssert matches[0] == "d" doAssert matches[0] == "d"
doAssert matches[1] == "g" doAssert matches[1] == "g"
else: else:
@ -1744,13 +1744,13 @@ when isMainModule:
for x in findAll("abcdef", peg"{.}", 3): for x in findAll("abcdef", peg"{.}", 3):
echo x echo x
if "f(a, b)" =~ peg"{[0-9]+} / ({\ident} '(' {@} ')')": if "f(a, b)" =~ peg"{[0-9]+} / ({\ident} '(' {@} ')')":
doAssert matches[0] == "f" doAssert matches[0] == "f"
doAssert matches[1] == "a, b" doAssert matches[1] == "a, b"
else: else:
doAssert false doAssert false
doAssert match("eine übersicht und außerdem", peg"(\letter \white*)+") doAssert match("eine übersicht und außerdem", peg"(\letter \white*)+")
# ß is not a lower cased letter?! # ß is not a lower cased letter?!
doAssert match("eine übersicht und auerdem", peg"(\lower \white*)+") doAssert match("eine übersicht und auerdem", peg"(\lower \white*)+")
@ -1762,7 +1762,7 @@ when isMainModule:
"var1<-keykey;var2<-key2key2") "var1<-keykey;var2<-key2key2")
doAssert match("prefix/start", peg"^start$", 7) doAssert match("prefix/start", peg"^start$", 7)
# tricky test to check for false aliasing: # tricky test to check for false aliasing:
block: block:
var a = term"key" var a = term"key"

View file

@ -9,8 +9,8 @@ when not defined(windows):
discard uname(u) discard uname(u)
writeln(stdout, u.sysname) writeLine(stdout, u.sysname)
writeln(stdout, u.nodename) writeLine(stdout, u.nodename)
writeln(stdout, u.release) writeLine(stdout, u.release)
writeln(stdout, u.machine) writeLine(stdout, u.machine)

View file

@ -9,7 +9,7 @@ type
var val = {a, b} var val = {a, b}
stdout.write(repr(val)) stdout.write(repr(val))
stdout.writeln(repr({'a'..'z', 'A'..'Z'})) stdout.writeLine(repr({'a'..'z', 'A'..'Z'}))
type type
TObj {.pure, inheritable.} = object TObj {.pure, inheritable.} = object

View file

@ -26,7 +26,7 @@ q[] = p
s = @[q, q, q, q] s = @[q, q, q, q]
writeln(stdout, repr(p)) writeLine(stdout, repr(p))
writeln(stdout, repr(q)) writeLine(stdout, repr(q))
writeln(stdout, repr(s)) writeLine(stdout, repr(s))
writeln(stdout, repr(en4)) writeLine(stdout, repr(en4))

View file

@ -1,12 +1,12 @@
import strtabs import strtabs
var tab = newStringTable({"key1": "val1", "key2": "val2"}, var tab = newStringTable({"key1": "val1", "key2": "val2"},
modeStyleInsensitive) modeStyleInsensitive)
for i in 0..80: for i in 0..80:
tab["key_" & $i] = "value" & $i tab["key_" & $i] = "value" & $i
for key, val in pairs(tab): for key, val in pairs(tab):
writeln(stdout, key, ": ", val) writeLine(stdout, key, ": ", val)
writeln(stdout, "length of table ", $tab.len) writeLine(stdout, "length of table ", $tab.len)
writeln(stdout, `%`("$key1 = $key2; ${PATH}", tab, {useEnvironment})) writeLine(stdout, `%`("$key1 = $key2; ${PATH}", tab, {useEnvironment}))

View file

@ -5,9 +5,9 @@ import
proc main(filter: string) = proc main(filter: string) =
for filename in walkFiles(filter): for filename in walkFiles(filter):
writeln(stdout, filename) writeLine(stdout, filename)
for key, val in envPairs(): for key, val in envPairs():
writeln(stdout, key & '=' & val) writeLine(stdout, key & '=' & val)
main("*.nim") main("*.nim")

View file

@ -15,10 +15,10 @@ var abclev = levB
template tstLev(abclev: TLev) = template tstLev(abclev: TLev) =
bind tstempl.abclev, `%` bind tstempl.abclev, `%`
writeln(stdout, "global = $1, arg = $2, test = $3" % [ writeLine(stdout, "global = $1, arg = $2, test = $3" % [
$tstempl.abclev, $abclev, $(tstempl.abclev == abclev)]) $tstempl.abclev, $abclev, $(tstempl.abclev == abclev)])
# evaluates to true, but must be false # evaluates to true, but must be false
tstLev(levA) tstLev(levA)
writeln(stdout, $abclev) writeLine(stdout, $abclev)

View file

@ -13,8 +13,8 @@ template withOpenFile(f: expr, filename: string, mode: TFileMode,
quit("cannot open for writing: " & filename) quit("cannot open for writing: " & filename)
withOpenFile(txt, "ttempl3.txt", fmWrite): withOpenFile(txt, "ttempl3.txt", fmWrite):
writeln(txt, "line 1") writeLine(txt, "line 1")
txt.writeln("line 2") txt.writeLine("line 2")
var var
myVar: array[0..1, int] myVar: array[0..1, int]

View file

@ -137,11 +137,11 @@ proc doScenario(script: string, output: Stream, mode: TRunMode, verbose: bool):
if line.strip.len == 0: continue if line.strip.len == 0: continue
if line.startsWith("#"): if line.startsWith("#"):
output.writeln line output.writeLine line
continue continue
elif line.startsWith(">"): elif line.startsWith(">"):
s.doCommand(line.substr(1).strip) s.doCommand(line.substr(1).strip)
output.writeln line, "\n", if verbose: s.lastOutput else: "" output.writeLine line, "\n", if verbose: s.lastOutput else: ""
else: else:
var expectMatch = true var expectMatch = true
var pattern = s.replaceVars(line) var pattern = s.replaceVars(line)
@ -153,9 +153,9 @@ proc doScenario(script: string, output: Stream, mode: TRunMode, verbose: bool):
s.lastOutput.find(re(pattern, flags = {reStudy})) != -1 s.lastOutput.find(re(pattern, flags = {reStudy})) != -1
if expectMatch == actualMatch: if expectMatch == actualMatch:
output.writeln "SUCCESS ", line output.writeLine "SUCCESS ", line
else: else:
output.writeln "FAILURE ", line output.writeLine "FAILURE ", line
result = false result = false
iterator caasTestsRunner*(filter = "", verbose = false): tuple[test, iterator caasTestsRunner*(filter = "", verbose = false): tuple[test,

View file

@ -138,7 +138,7 @@ proc generateHtml*(filename: string, commit: int; onlyFailing: bool) =
# generate navigation: # generate navigation:
outfile.write("""<ul id="tabs">""") outfile.write("""<ul id="tabs">""")
for m in db.rows(sql"select id, name, os, cpu from Machine order by id"): for m in db.rows(sql"select id, name, os, cpu from Machine order by id"):
outfile.writeln """<li><a href="#$#">$#: $#, $#</a></li>""" % m outfile.writeLine """<li><a href="#$#">$#: $#, $#</a></li>""" % m
outfile.write("</ul>") outfile.write("</ul>")
for currentMachine in db.rows(sql"select id from Machine order by id"): for currentMachine in db.rows(sql"select id from Machine order by id"):
@ -195,7 +195,7 @@ proc generateJson*(filename: string, commit: int) =
let machine = $backend.getMachine(db) let machine = $backend.getMachine(db)
let data = db.getRow(sql(selRow), lastCommit, machine) let data = db.getRow(sql(selRow), lastCommit, machine)
outfile.writeln("""{"total": $#, "passed": $#, "skipped": $#""" % data) outfile.writeLine("""{"total": $#, "passed": $#, "skipped": $#""" % data)
let results = newJArray() let results = newJArray()
for row in db.rows(sql(selResults), lastCommit): for row in db.rows(sql(selResults), lastCommit):
@ -208,7 +208,7 @@ proc generateJson*(filename: string, commit: int) =
obj["expected"] = %row[5] obj["expected"] = %row[5]
obj["given"] = %row[6] obj["given"] = %row[6]
results.add(obj) results.add(obj)
outfile.writeln(""", "results": """) outfile.writeLine(""", "results": """)
outfile.write(results.pretty) outfile.write(results.pretty)
if not previousCommit.isNil: if not previousCommit.isNil:
@ -220,9 +220,9 @@ proc generateJson*(filename: string, commit: int) =
obj["old"] = %row[1] obj["old"] = %row[1]
obj["new"] = %row[2] obj["new"] = %row[2]
diff.add obj diff.add obj
outfile.writeln(""", "diff": """) outfile.writeLine(""", "diff": """)
outfile.writeln(diff.pretty) outfile.writeLine(diff.pretty)
outfile.writeln "}" outfile.writeLine "}"
close(db) close(db)
close(outfile) close(outfile)

View file

@ -3,7 +3,7 @@ discard """
""" """
proc f(x: varargs[string, `$`]) = discard proc f(x: varargs[string, `$`]) = discard
template optF{f(x)}(x: varargs[expr]) = template optF{f(x)}(x: varargs[expr]) =
writeln(stdout, x) writeLine(stdout, x)
f 1, 2, false, 3, "ha" f 1, 2, false, 3, "ha"

View file

@ -7,13 +7,13 @@ discard """
template optWrite{ template optWrite{
write(f, x) write(f, x)
((write|writeln){w})(f, y) ((write|writeLine){w})(f, y)
}(x, y: varargs[expr], f, w: expr) = }(x, y: varargs[expr], f, w: expr) =
w(f, "|", x, y, "|") w(f, "|", x, y, "|")
if true: if true:
echo "0" echo "0"
write stdout, "1" write stdout, "1"
writeln stdout, "2" writeLine stdout, "2"
write stdout, "3" write stdout, "3"
echo "4" echo "4"

View file

@ -19,9 +19,9 @@ proc process(dir, infile: string, outfile: File,
ig <- (comment / \s+)* """: ig <- (comment / \s+)* """:
# follow the include file: # follow the include file:
if process(dir, matches[0], outfile, processed) == prAddIncludeDir: if process(dir, matches[0], outfile, processed) == prAddIncludeDir:
writeln(outfile, line) writeLine(outfile, line)
else: else:
writeln(outfile, line) writeLine(outfile, line)
proc main(dir, outfile: string) = proc main(dir, outfile: string) =
var o: File var o: File

View file

@ -21,10 +21,10 @@ Options:
--find, -f find the pattern (default) --find, -f find the pattern (default)
--replace, -r replace the pattern --replace, -r replace the pattern
--peg pattern is a peg --peg pattern is a peg
--re pattern is a regular expression (default); extended --re pattern is a regular expression (default); extended
syntax for the regular expression is always turned on syntax for the regular expression is always turned on
--recursive process directories recursively --recursive process directories recursively
--confirm confirm each occurrence/replacement; there is a chance --confirm confirm each occurrence/replacement; there is a chance
to abort any time without touching the file to abort any time without touching the file
--stdin read pattern from stdin (to avoid the shell's confusing --stdin read pattern from stdin (to avoid the shell's confusing
quoting rules) quoting rules)
@ -39,13 +39,13 @@ Options:
""" """
type type
TOption = enum TOption = enum
optFind, optReplace, optPeg, optRegex, optRecursive, optConfirm, optStdin, optFind, optReplace, optPeg, optRegex, optRecursive, optConfirm, optStdin,
optWord, optIgnoreCase, optIgnoreStyle, optVerbose optWord, optIgnoreCase, optIgnoreStyle, optVerbose
TOptions = set[TOption] TOptions = set[TOption]
TConfirmEnum = enum TConfirmEnum = enum
ceAbort, ceYes, ceAll, ceNo, ceNone ceAbort, ceYes, ceAll, ceNo, ceNone
var var
filenames: seq[string] = @[] filenames: seq[string] = @[]
pattern = "" pattern = ""
@ -58,34 +58,34 @@ proc ask(msg: string): string =
stdout.write(msg) stdout.write(msg)
result = stdin.readLine() result = stdin.readLine()
proc confirm: TConfirmEnum = proc confirm: TConfirmEnum =
while true: while true:
case normalize(ask(" [a]bort; [y]es, a[l]l, [n]o, non[e]: ")) case normalize(ask(" [a]bort; [y]es, a[l]l, [n]o, non[e]: "))
of "a", "abort": return ceAbort of "a", "abort": return ceAbort
of "y", "yes": return ceYes of "y", "yes": return ceYes
of "l", "all": return ceAll of "l", "all": return ceAll
of "n", "no": return ceNo of "n", "no": return ceNo
of "e", "none": return ceNone of "e", "none": return ceNone
else: discard else: discard
proc countLines(s: string, first, last: int): int = proc countLines(s: string, first, last: int): int =
var i = first var i = first
while i <= last: while i <= last:
if s[i] == '\13': if s[i] == '\13':
inc result inc result
if i < last and s[i+1] == '\10': inc(i) if i < last and s[i+1] == '\10': inc(i)
elif s[i] == '\10': elif s[i] == '\10':
inc result inc result
inc i inc i
proc beforePattern(s: string, first: int): int = proc beforePattern(s: string, first: int): int =
result = first-1 result = first-1
while result >= 0: while result >= 0:
if s[result] in NewLines: break if s[result] in NewLines: break
dec(result) dec(result)
inc(result) inc(result)
proc afterPattern(s: string, last: int): int = proc afterPattern(s: string, last: int): int =
result = last+1 result = last+1
while result < s.len: while result < s.len:
if s[result] in NewLines: break if s[result] in NewLines: break
@ -99,7 +99,7 @@ proc writeColored(s: string) =
stdout.write(s) stdout.write(s)
proc highlight(s, match, repl: string, t: tuple[first, last: int], proc highlight(s, match, repl: string, t: tuple[first, last: int],
line: int, showRepl: bool) = line: int, showRepl: bool) =
const alignment = 6 const alignment = 6
stdout.write(line.`$`.align(alignment), ": ") stdout.write(line.`$`.align(alignment), ": ")
var x = beforePattern(s, t.first) var x = beforePattern(s, t.first)
@ -118,17 +118,17 @@ proc highlight(s, match, repl: string, t: tuple[first, last: int],
proc processFile(filename: string) = proc processFile(filename: string) =
var filenameShown = false var filenameShown = false
template beforeHighlight = template beforeHighlight =
if not filenameShown and optVerbose notin options: if not filenameShown and optVerbose notin options:
stdout.writeln(filename) stdout.writeLine(filename)
filenameShown = true filenameShown = true
var buffer: string var buffer: string
try: try:
buffer = system.readFile(filename) buffer = system.readFile(filename)
except IOError: except IOError:
echo "cannot open file: ", filename echo "cannot open file: ", filename
return return
if optVerbose in options: stdout.writeln(filename) if optVerbose in options: stdout.writeLine(filename)
var pegp: TPeg var pegp: TPeg
var rep: Regex var rep: Regex
var result: string var result: string
@ -140,10 +140,10 @@ proc processFile(filename: string) =
rep = re(pattern) rep = re(pattern)
else: else:
pegp = peg(pattern) pegp = peg(pattern)
if optReplace in options: if optReplace in options:
result = newStringOfCap(buffer.len) result = newStringOfCap(buffer.len)
var line = 1 var line = 1
var i = 0 var i = 0
var matches: array[0..re.MaxSubpatterns-1, string] var matches: array[0..re.MaxSubpatterns-1, string]
@ -157,24 +157,24 @@ proc processFile(filename: string) =
t = findBounds(buffer, rep, matches, i) t = findBounds(buffer, rep, matches, i)
if t.first <= 0: break if t.first <= 0: break
inc(line, countLines(buffer, i, t.first-1)) inc(line, countLines(buffer, i, t.first-1))
var wholeMatch = buffer.substr(t.first, t.last) var wholeMatch = buffer.substr(t.first, t.last)
beforeHighlight() beforeHighlight()
if optReplace notin options: if optReplace notin options:
highlight(buffer, wholeMatch, "", t, line, showRepl=false) highlight(buffer, wholeMatch, "", t, line, showRepl=false)
else: else:
var r: string var r: string
if optRegex notin options: if optRegex notin options:
r = replace(wholeMatch, pegp, replacement % matches) r = replace(wholeMatch, pegp, replacement % matches)
else: else:
r = replace(wholeMatch, rep, replacement % matches) r = replace(wholeMatch, rep, replacement % matches)
if optConfirm in options: if optConfirm in options:
highlight(buffer, wholeMatch, r, t, line, showRepl=true) highlight(buffer, wholeMatch, r, t, line, showRepl=true)
case confirm() case confirm()
of ceAbort: quit(0) of ceAbort: quit(0)
of ceYes: reallyReplace = true of ceYes: reallyReplace = true
of ceAll: of ceAll:
reallyReplace = true reallyReplace = true
options.excl(optConfirm) options.excl(optConfirm)
of ceNo: of ceNo:
@ -203,11 +203,11 @@ proc processFile(filename: string) =
proc hasRightExt(filename: string, exts: seq[string]): bool = proc hasRightExt(filename: string, exts: seq[string]): bool =
var y = splitFile(filename).ext.substr(1) # skip leading '.' var y = splitFile(filename).ext.substr(1) # skip leading '.'
for x in items(exts): for x in items(exts):
if os.cmpPaths(x, y) == 0: return true if os.cmpPaths(x, y) == 0: return true
proc styleInsensitive(s: string): string = proc styleInsensitive(s: string): string =
template addx: stmt = template addx: stmt =
result.add(s[i]) result.add(s[i])
inc(i) inc(i)
result = "" result = ""
@ -215,7 +215,7 @@ proc styleInsensitive(s: string): string =
var brackets = 0 var brackets = 0
while i < s.len: while i < s.len:
case s[i] case s[i]
of 'A'..'Z', 'a'..'z', '0'..'9': of 'A'..'Z', 'a'..'z', '0'..'9':
addx() addx()
if brackets == 0: result.add("_?") if brackets == 0: result.add("_?")
of '_': of '_':
@ -234,29 +234,29 @@ proc styleInsensitive(s: string): string =
while s[i] != '>' and s[i] != '\0': addx() while s[i] != '>' and s[i] != '\0': addx()
of '\\': of '\\':
addx() addx()
if s[i] in strutils.Digits: if s[i] in strutils.Digits:
while s[i] in strutils.Digits: addx() while s[i] in strutils.Digits: addx()
else: else:
addx() addx()
else: addx() else: addx()
proc walker(dir: string) = proc walker(dir: string) =
for kind, path in walkDir(dir): for kind, path in walkDir(dir):
case kind case kind
of pcFile: of pcFile:
if extensions.len == 0 or path.hasRightExt(extensions): if extensions.len == 0 or path.hasRightExt(extensions):
processFile(path) processFile(path)
of pcDir: of pcDir:
if optRecursive in options: if optRecursive in options:
walker(path) walker(path)
else: discard else: discard
if existsFile(dir): processFile(dir) if existsFile(dir): processFile(dir)
proc writeHelp() = proc writeHelp() =
stdout.write(Usage) stdout.write(Usage)
quit(0) quit(0)
proc writeVersion() = proc writeVersion() =
stdout.write(Version & "\n") stdout.write(Version & "\n")
quit(0) quit(0)
@ -267,9 +267,9 @@ proc checkOptions(subset: TOptions, a, b: string) =
for kind, key, val in getopt(): for kind, key, val in getopt():
case kind case kind
of cmdArgument: of cmdArgument:
if options.contains(optStdin): if options.contains(optStdin):
filenames.add(key) filenames.add(key)
elif pattern.len == 0: elif pattern.len == 0:
pattern = key pattern = key
elif options.contains(optReplace) and replacement.len == 0: elif options.contains(optReplace) and replacement.len == 0:
replacement = key replacement = key
@ -306,7 +306,7 @@ checkOptions({optFind, optReplace}, "find", "replace")
checkOptions({optPeg, optRegex}, "peg", "re") checkOptions({optPeg, optRegex}, "peg", "re")
checkOptions({optIgnoreCase, optIgnoreStyle}, "ignore_case", "ignore_style") checkOptions({optIgnoreCase, optIgnoreStyle}, "ignore_case", "ignore_style")
if optStdin in options: if optStdin in options:
pattern = ask("pattern [ENTER to exit]: ") pattern = ask("pattern [ENTER to exit]: ")
if isNil(pattern) or pattern.len == 0: quit(0) if isNil(pattern) or pattern.len == 0: quit(0)
if optReplace in options: if optReplace in options:
@ -314,18 +314,18 @@ if optStdin in options:
if pattern.len == 0: if pattern.len == 0:
writeHelp() writeHelp()
else: else:
if filenames.len == 0: if filenames.len == 0:
filenames.add(os.getCurrentDir()) filenames.add(os.getCurrentDir())
if optRegex notin options: if optRegex notin options:
if optWord in options: if optWord in options:
pattern = r"(^ / !\letter)(" & pattern & r") !\letter" pattern = r"(^ / !\letter)(" & pattern & r") !\letter"
if optIgnoreStyle in options: if optIgnoreStyle in options:
pattern = "\\y " & pattern pattern = "\\y " & pattern
elif optIgnoreCase in options: elif optIgnoreCase in options:
pattern = "\\i " & pattern pattern = "\\i " & pattern
else: else:
if optIgnoreStyle in options: if optIgnoreStyle in options:
pattern = styleInsensitive(pattern) pattern = styleInsensitive(pattern)
if optWord in options: if optWord in options:
pattern = r"\b (:?" & pattern & r") \b" pattern = r"\b (:?" & pattern & r") \b"

View file

@ -126,10 +126,10 @@ proc parseCmdLine(c: var TConfigData) =
break break
of cmdLongOption, cmdShortOption: of cmdLongOption, cmdShortOption:
case normalize(key) case normalize(key)
of "help", "h": of "help", "h":
stdout.write(usage) stdout.write(usage)
quit(0) quit(0)
of "version", "v": of "version", "v":
stdout.write(version & "\n") stdout.write(version & "\n")
quit(0) quit(0)
of "o", "output": c.outdir = val of "o", "output": c.outdir = val
@ -431,7 +431,7 @@ proc buildWebsite(c: var TConfigData) =
if not existsDir("web/upload"): if not existsDir("web/upload"):
createDir("web/upload") createDir("web/upload")
if open(f, outfile, fmWrite): if open(f, outfile, fmWrite):
writeln(f, generateHTMLPage(c, file, content, rss)) writeLine(f, generateHTMLPage(c, file, content, rss))
close(f) close(f)
else: else:
quit("[Error] cannot write file: " & outfile) quit("[Error] cannot write file: " & outfile)